@graphql-eslint/eslint-plugin 3.14.4-alpha-20230111223410-a558ee8 → 3.14.4-alpha-20230111225020-02d9c28
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +5 -288
- package/cjs/documents.js +2 -105
- package/cjs/graphql-config.js +1 -1
- package/cjs/parser.js +9 -3
- package/cjs/rules/alphabetize.js +1 -1
- package/cjs/rules/description-style.js +1 -1
- package/cjs/rules/graphql-js-validation.js +1 -1
- package/cjs/rules/input-name.js +4 -4
- package/cjs/rules/lone-executable-definition.js +1 -1
- package/cjs/rules/match-document-filename.js +2 -3
- package/cjs/rules/naming-convention.js +1 -1
- package/cjs/rules/no-anonymous-operations.js +1 -1
- package/cjs/rules/no-case-insensitive-enum-values-duplicates.js +1 -1
- package/cjs/rules/no-deprecated.js +1 -1
- package/cjs/rules/no-duplicate-fields.js +1 -1
- package/cjs/rules/no-hashtag-description.js +1 -1
- package/cjs/rules/no-one-place-fragments.js +1 -1
- package/cjs/rules/no-root-type.js +1 -1
- package/cjs/rules/no-scalar-result-type-on-mutation.js +1 -1
- package/cjs/rules/no-typename-prefix.js +1 -1
- package/cjs/rules/no-unreachable-types.js +1 -1
- package/cjs/rules/no-unused-fields.js +1 -1
- package/cjs/rules/relay-arguments.js +1 -1
- package/cjs/rules/relay-connection-types.js +1 -1
- package/cjs/rules/relay-edge-types.js +1 -1
- package/cjs/rules/relay-page-info.js +1 -1
- package/cjs/rules/require-deprecation-date.js +1 -1
- package/cjs/rules/require-deprecation-reason.js +1 -1
- package/cjs/rules/require-description.js +1 -1
- package/cjs/rules/require-field-of-type-query-in-mutation-result.js +1 -1
- package/cjs/rules/require-id-when-available.js +1 -1
- package/cjs/rules/require-nullable-fields-with-oneof.js +1 -1
- package/cjs/rules/require-type-pattern-with-oneof.js +1 -1
- package/cjs/rules/selection-set-depth.js +1 -1
- package/cjs/rules/strict-id-in-types.js +1 -1
- package/cjs/rules/unique-fragment-name.js +1 -1
- package/cjs/rules/unique-operation-name.js +1 -1
- package/cjs/siblings.js +113 -0
- package/cjs/utils.js +2 -1
- package/docs/README.md +1 -85
- package/docs/custom-rules.md +1 -184
- package/docs/deprecated-rules.md +1 -24
- package/docs/parser-options.md +1 -107
- package/docs/parser.md +1 -67
- package/esm/documents.js +2 -105
- package/esm/graphql-config.js +1 -1
- package/esm/parser.js +10 -4
- package/esm/rules/alphabetize.js +1 -1
- package/esm/rules/description-style.js +1 -1
- package/esm/rules/graphql-js-validation.js +1 -1
- package/esm/rules/input-name.js +4 -4
- package/esm/rules/lone-executable-definition.js +1 -1
- package/esm/rules/match-document-filename.js +3 -4
- package/esm/rules/naming-convention.js +1 -1
- package/esm/rules/no-anonymous-operations.js +1 -1
- package/esm/rules/no-case-insensitive-enum-values-duplicates.js +1 -1
- package/esm/rules/no-deprecated.js +1 -1
- package/esm/rules/no-duplicate-fields.js +1 -1
- package/esm/rules/no-hashtag-description.js +1 -1
- package/esm/rules/no-one-place-fragments.js +1 -1
- package/esm/rules/no-root-type.js +1 -1
- package/esm/rules/no-scalar-result-type-on-mutation.js +1 -1
- package/esm/rules/no-typename-prefix.js +1 -1
- package/esm/rules/no-unreachable-types.js +1 -1
- package/esm/rules/no-unused-fields.js +1 -1
- package/esm/rules/relay-arguments.js +1 -1
- package/esm/rules/relay-connection-types.js +1 -1
- package/esm/rules/relay-edge-types.js +1 -1
- package/esm/rules/relay-page-info.js +1 -1
- package/esm/rules/require-deprecation-date.js +1 -1
- package/esm/rules/require-deprecation-reason.js +1 -1
- package/esm/rules/require-description.js +1 -1
- package/esm/rules/require-field-of-type-query-in-mutation-result.js +1 -1
- package/esm/rules/require-id-when-available.js +1 -1
- package/esm/rules/require-nullable-fields-with-oneof.js +1 -1
- package/esm/rules/require-type-pattern-with-oneof.js +1 -1
- package/esm/rules/selection-set-depth.js +1 -1
- package/esm/rules/strict-id-in-types.js +1 -1
- package/esm/rules/unique-fragment-name.js +1 -1
- package/esm/rules/unique-operation-name.js +1 -1
- package/esm/siblings.js +109 -0
- package/esm/utils.js +1 -0
- package/package.json +1 -1
- package/typings/documents.d.cts +2 -20
- package/typings/documents.d.ts +2 -20
- package/typings/rules/input-name.d.cts +1 -1
- package/typings/rules/input-name.d.ts +1 -1
- package/typings/siblings.d.cts +22 -0
- package/typings/siblings.d.ts +22 -0
- package/typings/types.d.cts +3 -2
- package/typings/types.d.ts +3 -2
- package/typings/utils.d.cts +2 -1
- package/typings/utils.d.ts +2 -1
- package/docs/rules/alphabetize.md +0 -194
- package/docs/rules/description-style.md +0 -57
- package/docs/rules/executable-definitions.md +0 -20
- package/docs/rules/fields-on-correct-type.md +0 -23
- package/docs/rules/fragments-on-composite-type.md +0 -20
- package/docs/rules/input-name.md +0 -80
- package/docs/rules/known-argument-names.md +0 -23
- package/docs/rules/known-directives.md +0 -48
- package/docs/rules/known-fragment-names.md +0 -72
- package/docs/rules/known-type-names.md +0 -24
- package/docs/rules/lone-anonymous-operation.md +0 -20
- package/docs/rules/lone-executable-definition.md +0 -59
- package/docs/rules/lone-schema-definition.md +0 -19
- package/docs/rules/match-document-filename.md +0 -181
- package/docs/rules/naming-convention.md +0 -320
- package/docs/rules/no-anonymous-operations.md +0 -43
- package/docs/rules/no-case-insensitive-enum-values-duplicates.md +0 -46
- package/docs/rules/no-deprecated.md +0 -88
- package/docs/rules/no-duplicate-fields.md +0 -69
- package/docs/rules/no-fragment-cycles.md +0 -19
- package/docs/rules/no-hashtag-description.md +0 -62
- package/docs/rules/no-one-place-fragments.md +0 -51
- package/docs/rules/no-root-type.md +0 -55
- package/docs/rules/no-scalar-result-type-on-mutation.md +0 -39
- package/docs/rules/no-typename-prefix.md +0 -42
- package/docs/rules/no-undefined-variables.md +0 -20
- package/docs/rules/no-unreachable-types.md +0 -52
- package/docs/rules/no-unused-fields.md +0 -64
- package/docs/rules/no-unused-fragments.md +0 -20
- package/docs/rules/no-unused-variables.md +0 -20
- package/docs/rules/one-field-subscriptions.md +0 -19
- package/docs/rules/overlapping-fields-can-be-merged.md +0 -20
- package/docs/rules/possible-fragment-spread.md +0 -21
- package/docs/rules/possible-type-extension.md +0 -19
- package/docs/rules/provided-required-arguments.md +0 -21
- package/docs/rules/relay-arguments.md +0 -59
- package/docs/rules/relay-connection-types.md +0 -43
- package/docs/rules/relay-edge-types.md +0 -60
- package/docs/rules/relay-page-info.md +0 -34
- package/docs/rules/require-deprecation-date.md +0 -59
- package/docs/rules/require-deprecation-reason.md +0 -49
- package/docs/rules/require-description.md +0 -147
- package/docs/rules/require-field-of-type-query-in-mutation-result.md +0 -50
- package/docs/rules/require-id-when-available.md +0 -91
- package/docs/rules/require-nullable-fields-with-oneof.md +0 -38
- package/docs/rules/require-type-pattern-with-oneof.md +0 -39
- package/docs/rules/scalar-leafs.md +0 -23
- package/docs/rules/selection-set-depth.md +0 -86
- package/docs/rules/strict-id-in-types.md +0 -129
- package/docs/rules/unique-argument-names.md +0 -19
- package/docs/rules/unique-directive-names-per-location.md +0 -21
- package/docs/rules/unique-directive-names.md +0 -19
- package/docs/rules/unique-enum-value-names.md +0 -16
- package/docs/rules/unique-field-definition-names.md +0 -19
- package/docs/rules/unique-fragment-name.md +0 -52
- package/docs/rules/unique-input-field-names.md +0 -19
- package/docs/rules/unique-operation-name.md +0 -56
- package/docs/rules/unique-operation-types.md +0 -19
- package/docs/rules/unique-type-names.md +0 -19
- package/docs/rules/unique-variable-names.md +0 -19
- package/docs/rules/value-literals-of-correct-type.md +0 -22
- package/docs/rules/variables-are-input-types.md +0 -20
- package/docs/rules/variables-in-allowed-position.md +0 -19
package/README.md
CHANGED
@@ -1,293 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
<img height="150" src="./logo.png">
|
1
|
+
# GraphQL-ESLint
|
4
2
|
|
5
3
|
[![npm version](https://badge.fury.io/js/%40graphql-eslint%2Feslint-plugin.svg)](https://badge.fury.io/js/%40graphql-eslint%2Feslint-plugin)
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
## Key Features
|
10
|
-
|
11
|
-
- 🚀 Integrates with ESLint core (as a ESTree parser)
|
12
|
-
- 🚀 Works on `.graphql` files, `gql` usages and `/* GraphQL */` magic comments
|
13
|
-
- 🚀 Lints both GraphQL schema and GraphQL operations
|
14
|
-
- 🚀 Extended type info for more advanced usages
|
15
|
-
- 🚀 Supports ESLint directives (for example: `eslint-disable-next-line`)
|
16
|
-
- 🚀 Easily extendable - supports custom rules based on GraphQL's AST and ESLint API
|
17
|
-
- 🚀 Validates, lints, prettifies and checks for best practices across GraphQL schema and GraphQL
|
18
|
-
operations
|
19
|
-
- 🚀 Integrates with [`graphql-config`](https://graphql-config.com)
|
20
|
-
- 🚀 Integrates and visualizes lint issues in popular IDEs (VSCode / WebStorm)
|
21
|
-
|
22
|
-
> Special thanks to [ilyavolodin](https://github.com/ilyavolodin) for his work on a similar project!
|
23
|
-
|
24
|
-
<img src="https://thumbs.gfycat.com/ActualTerrificDog-size_restricted.gif" />
|
25
|
-
|
26
|
-
## Getting Started
|
27
|
-
|
28
|
-
- [Introducing GraphQL-ESLint!](https://the-guild.dev/blog/introducing-graphql-eslint) @
|
29
|
-
`the-guild.dev`
|
30
|
-
|
31
|
-
### Installation
|
32
|
-
|
33
|
-
Start by installing the plugin package, which includes everything you need:
|
34
|
-
|
35
|
-
```sh
|
36
|
-
yarn add -D @graphql-eslint/eslint-plugin
|
37
|
-
```
|
38
|
-
|
39
|
-
Or, with NPM:
|
40
|
-
|
41
|
-
```sh
|
42
|
-
npm install --save-dev @graphql-eslint/eslint-plugin
|
43
|
-
```
|
44
|
-
|
45
|
-
> Make sure you have `graphql` dependency in your project.
|
46
|
-
|
47
|
-
## Configuration
|
48
|
-
|
49
|
-
To get started, define an override in your ESLint config to apply this plugin to `.graphql` files.
|
50
|
-
Add the [rules](docs/README.md) you want applied.
|
51
|
-
|
52
|
-
> 🚨 Important! This step is necessary even if you are declaring operations and/or schema in code
|
53
|
-
> files.
|
54
|
-
|
55
|
-
```json
|
56
|
-
{
|
57
|
-
"overrides": [
|
58
|
-
{
|
59
|
-
"files": ["*.graphql"],
|
60
|
-
"parser": "@graphql-eslint/eslint-plugin",
|
61
|
-
"plugins": ["@graphql-eslint"],
|
62
|
-
"rules": {
|
63
|
-
"@graphql-eslint/known-type-names": "error"
|
64
|
-
}
|
65
|
-
}
|
66
|
-
]
|
67
|
-
}
|
68
|
-
```
|
69
|
-
|
70
|
-
If your GraphQL definitions are defined only in `.graphql` files, and you're only using rules that
|
71
|
-
apply to individual files, you should be good to go 👍. If you would like use a remote schema or use
|
72
|
-
rules that apply across the entire collection of definitions at once, see
|
73
|
-
[here](#extended-linting-rules-with-graphql-schema).
|
74
|
-
|
75
|
-
### Apply this plugin to GraphQL definitions defined in code files
|
76
|
-
|
77
|
-
If you are defining GraphQL schema or GraphQL operations in code files, you'll want to define an
|
78
|
-
additional override to extend the functionality of this plugin to the schema and operations in those
|
79
|
-
files.
|
80
|
-
|
81
|
-
```diff
|
82
|
-
{
|
83
|
-
"overrides": [
|
84
|
-
+ {
|
85
|
-
+ "files": ["*.js"],
|
86
|
-
+ "processor": "@graphql-eslint/graphql"
|
87
|
-
+ },
|
88
|
-
{
|
89
|
-
"files": ["*.graphql"],
|
90
|
-
"parser": "@graphql-eslint/eslint-plugin",
|
91
|
-
"plugins": ["@graphql-eslint"],
|
92
|
-
"rules": {
|
93
|
-
"@graphql-eslint/known-type-names": "error"
|
94
|
-
}
|
95
|
-
}
|
96
|
-
]
|
97
|
-
}
|
98
|
-
```
|
99
|
-
|
100
|
-
Under the hood, specifying the `@graphql-eslint/graphql` processor for code files will cause
|
101
|
-
`graphql-eslint/graphql` to extract the schema and operation definitions from these files into
|
102
|
-
virtual GraphQL documents with `.graphql` extensions. This will allow the overrides you've defined
|
103
|
-
for `.graphql` files, via `"files": ["*.graphql"]`, to get applied to the definitions defined in
|
104
|
-
your code files.
|
105
|
-
|
106
|
-
### Extended linting rules with GraphQL Schema
|
107
|
-
|
108
|
-
Some rules require an understanding of the entire schema at once. For example,
|
109
|
-
[no-unreachable-types](https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/no-unreachable-types.md#no-unreachable-types)
|
110
|
-
checks that all types are reachable by root-level fields.
|
111
|
-
|
112
|
-
To use these rules, you'll need to tell ESLint how to identify the entire set of schema definitions.
|
113
|
-
|
114
|
-
If you are using [`graphql-config`](https://graphql-config.com), you are good to go.
|
115
|
-
`graphql-eslint` integrates with it automatically and will use it to load your schema!
|
116
|
-
|
117
|
-
Alternatively, you can define `parserOptions.schema` in the `*.graphql` override in your ESLint
|
118
|
-
config.
|
119
|
-
|
120
|
-
The parser allows you to specify a json file / graphql files(s) / url / raw string to locate your
|
121
|
-
schema (We are using `graphql-tools` to do that). Just add `parserOptions.schema` to your
|
122
|
-
configuration file:
|
123
|
-
|
124
|
-
```diff
|
125
|
-
{
|
126
|
-
"files": ["*.graphql"],
|
127
|
-
"parser": "@graphql-eslint/eslint-plugin",
|
128
|
-
"plugins": ["@graphql-eslint"],
|
129
|
-
"rules": {
|
130
|
-
"@graphql-eslint/no-unreachable-types": "error"
|
131
|
-
},
|
132
|
-
+ "parserOptions": {
|
133
|
-
+ "schema": "./schema.graphql"
|
134
|
-
+ }
|
135
|
-
}
|
136
|
-
```
|
137
|
-
|
138
|
-
> You can find a complete [documentation of the `parserOptions` here](docs/parser-options.md).
|
139
|
-
|
140
|
-
> Some rules require type information to operate, it's marked in the docs for each rule!
|
141
|
-
|
142
|
-
### Extended linting rules with siblings operations
|
143
|
-
|
144
|
-
While implementing this tool, we had to find solutions for a better integration of the GraphQL
|
145
|
-
ecosystem and ESLint core.
|
146
|
-
|
147
|
-
GraphQL's operations can be distributed across many files, while ESLint operates on one file at a
|
148
|
-
time. If you are using GraphQL fragments in separate files, some rules might yield incorrect
|
149
|
-
results, due the missing information.
|
150
|
-
|
151
|
-
To workaround that, we allow you to provide additional information on your GraphQL operations,
|
152
|
-
making it available for rules while doing the actual linting.
|
153
|
-
|
154
|
-
To provide that, we are using `graphql-tools` loaders to load your sibling operations and fragments,
|
155
|
-
just specify a glob expression(s) that points to your code/`.graphql` files:
|
156
|
-
|
157
|
-
```diff
|
158
|
-
{
|
159
|
-
"files": ["*.graphql"],
|
160
|
-
"parser": "@graphql-eslint/eslint-plugin",
|
161
|
-
"plugins": ["@graphql-eslint"],
|
162
|
-
"rules": {
|
163
|
-
"@graphql-eslint/unique-operation-name": "error"
|
164
|
-
},
|
165
|
-
"parserOptions": {
|
166
|
-
+ "operations": "./src/**/*.graphql",
|
167
|
-
"schema": "./schema.graphql"
|
168
|
-
}
|
169
|
-
}
|
170
|
-
```
|
171
|
-
|
172
|
-
### VSCode Integration
|
173
|
-
|
174
|
-
Use
|
175
|
-
[ESLint VSCode extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
|
176
|
-
to integrate ESLint into VSCode.
|
177
|
-
|
178
|
-
For syntax highlighting you need a GraphQL extension (which may potentially have its own linting),
|
179
|
-
for example
|
180
|
-
[GraphQL (by GraphQL Foundation)](https://marketplace.visualstudio.com/items?itemName=GraphQL.vscode-graphql).
|
181
|
-
|
182
|
-
### Disabling Rules
|
183
|
-
|
184
|
-
The `graphql-eslint` parser looks for GraphQL comments syntax (marked with `#`) and will send it to
|
185
|
-
ESLint as directives. That means, you can use ESLint directives syntax to hint ESLint, just like in
|
186
|
-
any other type of files.
|
187
|
-
|
188
|
-
To disable ESLint for a specific line, you can do:
|
189
|
-
|
190
|
-
```graphql
|
191
|
-
# eslint-disable-next-line
|
192
|
-
type Query {
|
193
|
-
foo: String!
|
194
|
-
}
|
195
|
-
```
|
196
|
-
|
197
|
-
You can also specify specific rules to disable, apply it over the entire file,
|
198
|
-
`eslint-disable-next-line` or current `eslint-disable-line`.
|
199
|
-
|
200
|
-
You can find a list of
|
201
|
-
[ESLint directives here](https://eslint.org/docs/2.13.1/user-guide/configuring#disabling-rules-with-inline-comments).
|
202
|
-
|
203
|
-
## Available Rules
|
204
|
-
|
205
|
-
You can find a complete list of [all available rules here](docs/README.md).
|
206
|
-
|
207
|
-
### Deprecated Rules
|
208
|
-
|
209
|
-
See [docs/deprecated-rules.md](docs/deprecated-rules.md).
|
210
|
-
|
211
|
-
## Available Configs
|
212
|
-
|
213
|
-
<!-- prettier-ignore-start -->
|
214
|
-
|Name|Description|
|
215
|
-
|:-:|-|
|
216
|
-
|[`schema-recommended`](packages/plugin/src/configs/schema-recommended.ts)|enables recommended rules for schema (SDL) development|
|
217
|
-
|[`schema-all`](packages/plugin/src/configs/schema-all.ts)|enables all rules for schema (SDL) development, except for those that require `parserOptions.operations` option|
|
218
|
-
|[`operations-recommended`](packages/plugin/src/configs/operations-recommended.ts) |enables recommended rules for consuming GraphQL (operations) development|
|
219
|
-
|[`operations-all`](packages/plugin/src/configs/operations-all.ts)|enables all rules for consuming GraphQL (operations) development|
|
220
|
-
|[`relay`](packages/plugin/src/configs/relay.ts)|enables rules from Relay specification for schema (SDL) development|
|
221
|
-
<!-- prettier-ignore-end -->
|
222
|
-
|
223
|
-
> If you are in a project that develops the GraphQL schema, you'll need `schema` rules.
|
224
|
-
|
225
|
-
> If you are in a project that develops GraphQL operations (query/mutation/subscription), you'll
|
226
|
-
> need `operations` rules.
|
227
|
-
|
228
|
-
> If you are in a monorepo project, you probably need both sets of rules, see
|
229
|
-
> [example of configuration](examples/monorepo/eslint.config.js).
|
230
|
-
|
231
|
-
### Config usage
|
232
|
-
|
233
|
-
For example, to enable the `schema-recommended` config, enable it in your `.eslintrc` file with the
|
234
|
-
`extends` option:
|
235
|
-
|
236
|
-
> All configs under the hood set `parser` as `@graphql-eslint/eslint-plugin` and add
|
237
|
-
> `@graphql-eslint` to `plugins` array, so you don't need to specify them.
|
238
|
-
|
239
|
-
```diff
|
240
|
-
{
|
241
|
-
"overrides": [
|
242
|
-
{
|
243
|
-
"files": ["*.js"],
|
244
|
-
"processor": "@graphql-eslint/graphql"
|
245
|
-
},
|
246
|
-
{
|
247
|
-
"files": ["*.graphql"],
|
248
|
-
- "parser": "@graphql-eslint/eslint-plugin",
|
249
|
-
- "plugins": ["@graphql-eslint"],
|
250
|
-
+ "extends": "plugin:@graphql-eslint/schema-recommended"
|
251
|
-
}
|
252
|
-
]
|
253
|
-
}
|
254
|
-
```
|
255
|
-
|
256
|
-
### `prettier` rule
|
257
|
-
|
258
|
-
`eslint-plugin-prettier` supports `.graphql` files, and `v4.1.0` supports `graphql` blocks even
|
259
|
-
better. You need to do the following:
|
260
|
-
|
261
|
-
```js
|
262
|
-
module.exports = {
|
263
|
-
overrides: [
|
264
|
-
{
|
265
|
-
files: ['*.js'],
|
266
|
-
processor: '@graphql-eslint/graphql',
|
267
|
-
extends: ['plugin:prettier/recommended']
|
268
|
-
},
|
269
|
-
{
|
270
|
-
files: ['*.graphql'],
|
271
|
-
parser: '@graphql-eslint/eslint-plugin',
|
272
|
-
plugins: ['@graphql-eslint'],
|
273
|
-
rules: {
|
274
|
-
'prettier/prettier': 'error'
|
275
|
-
}
|
276
|
-
}
|
277
|
-
]
|
278
|
-
}
|
279
|
-
```
|
280
|
-
|
281
|
-
You can take [`examples/prettier`](examples/prettier/eslint.config.js) as example.
|
282
|
-
|
283
|
-
## Further Reading
|
284
|
-
|
285
|
-
If you wish to learn more about this project, how the parser works, how to add custom rules and more
|
286
|
-
please refer to the below links:
|
5
|
+
## Documentation
|
287
6
|
|
288
|
-
-
|
289
|
-
- [How the parser works?](docs/parser.md)
|
290
|
-
- [`parserOptions`](docs/parser-options.md)
|
7
|
+
[https://the-guild.dev/graphql/eslint](https://the-guild.dev/graphql/eslint)
|
291
8
|
|
292
9
|
## Contributions
|
293
10
|
|
@@ -298,7 +15,7 @@ And if this is your first time contributing to this project, please do read our
|
|
298
15
|
[Contributor Workflow Guide](https://github.com/the-guild-org/Stack/blob/master/CONTRIBUTING.md)
|
299
16
|
before you get started off.
|
300
17
|
|
301
|
-
|
18
|
+
## Code of Conduct
|
302
19
|
|
303
20
|
Help us keep GraphQL ESLint open and inclusive. Please read and follow our
|
304
21
|
[Code of Conduct](https://github.com/the-guild-org/Stack/blob/master/CODE_OF_CONDUCT.md) as adopted
|
@@ -306,4 +23,4 @@ from [Contributor Covenant](https://contributor-covenant.org).
|
|
306
23
|
|
307
24
|
## License
|
308
25
|
|
309
|
-
Released under the [MIT license](LICENSE).
|
26
|
+
Released under the [MIT license](./LICENSE).
|
package/cjs/documents.js
CHANGED
@@ -5,10 +5,9 @@ const tslib_1 = require("tslib");
|
|
5
5
|
const path_1 = require("path");
|
6
6
|
const debug_1 = tslib_1.__importDefault(require("debug"));
|
7
7
|
const fast_glob_1 = tslib_1.__importDefault(require("fast-glob"));
|
8
|
-
const graphql_1 = require("graphql");
|
9
8
|
const cache_js_1 = require("./cache.js");
|
10
|
-
const utils_js_1 = require("./utils.js");
|
11
9
|
const debug = (0, debug_1.default)('graphql-eslint:operations');
|
10
|
+
const operationsCache = new cache_js_1.ModuleCache();
|
12
11
|
const handleVirtualPath = (documents) => {
|
13
12
|
const filepathMap = Object.create(null);
|
14
13
|
return documents.map(source => {
|
@@ -25,9 +24,7 @@ const handleVirtualPath = (documents) => {
|
|
25
24
|
};
|
26
25
|
});
|
27
26
|
};
|
28
|
-
const
|
29
|
-
const siblingOperationsCache = new Map();
|
30
|
-
const getSiblings = (project) => {
|
27
|
+
const getDocuments = (project) => {
|
31
28
|
const documentsKey = project.documents;
|
32
29
|
if (!documentsKey) {
|
33
30
|
return [];
|
@@ -49,104 +46,4 @@ const getSiblings = (project) => {
|
|
49
46
|
}
|
50
47
|
return siblings;
|
51
48
|
};
|
52
|
-
function getDocuments(project) {
|
53
|
-
const siblings = getSiblings(project);
|
54
|
-
if (siblings.length === 0) {
|
55
|
-
let printed = false;
|
56
|
-
const noopWarn = () => {
|
57
|
-
if (!printed) {
|
58
|
-
utils_js_1.logger.warn('getSiblingOperations was called without any operations. Make sure to set "parserOptions.operations" to make this feature available!');
|
59
|
-
printed = true;
|
60
|
-
}
|
61
|
-
return [];
|
62
|
-
};
|
63
|
-
return {
|
64
|
-
available: false,
|
65
|
-
getFragment: noopWarn,
|
66
|
-
getFragments: noopWarn,
|
67
|
-
getFragmentByType: noopWarn,
|
68
|
-
getFragmentsInUse: noopWarn,
|
69
|
-
getOperation: noopWarn,
|
70
|
-
getOperations: noopWarn,
|
71
|
-
getOperationByType: noopWarn,
|
72
|
-
};
|
73
|
-
}
|
74
|
-
// Since the siblings array is cached, we can use it as cache key.
|
75
|
-
// We should get the same array reference each time we get
|
76
|
-
// to this point for the same graphql project
|
77
|
-
const value = siblingOperationsCache.get(siblings);
|
78
|
-
if (value) {
|
79
|
-
return value;
|
80
|
-
}
|
81
|
-
let fragmentsCache = null;
|
82
|
-
const getFragments = () => {
|
83
|
-
var _a;
|
84
|
-
if (fragmentsCache === null) {
|
85
|
-
const result = [];
|
86
|
-
for (const source of siblings) {
|
87
|
-
for (const definition of ((_a = source.document) === null || _a === void 0 ? void 0 : _a.definitions) || []) {
|
88
|
-
if (definition.kind === graphql_1.Kind.FRAGMENT_DEFINITION) {
|
89
|
-
result.push({
|
90
|
-
filePath: source.location,
|
91
|
-
document: definition,
|
92
|
-
});
|
93
|
-
}
|
94
|
-
}
|
95
|
-
}
|
96
|
-
fragmentsCache = result;
|
97
|
-
}
|
98
|
-
return fragmentsCache;
|
99
|
-
};
|
100
|
-
let cachedOperations = null;
|
101
|
-
const getOperations = () => {
|
102
|
-
var _a;
|
103
|
-
if (cachedOperations === null) {
|
104
|
-
const result = [];
|
105
|
-
for (const source of siblings) {
|
106
|
-
for (const definition of ((_a = source.document) === null || _a === void 0 ? void 0 : _a.definitions) || []) {
|
107
|
-
if (definition.kind === graphql_1.Kind.OPERATION_DEFINITION) {
|
108
|
-
result.push({
|
109
|
-
filePath: source.location,
|
110
|
-
document: definition,
|
111
|
-
});
|
112
|
-
}
|
113
|
-
}
|
114
|
-
}
|
115
|
-
cachedOperations = result;
|
116
|
-
}
|
117
|
-
return cachedOperations;
|
118
|
-
};
|
119
|
-
const getFragment = (name) => getFragments().filter(f => { var _a; return ((_a = f.document.name) === null || _a === void 0 ? void 0 : _a.value) === name; });
|
120
|
-
const collectFragments = (selectable, recursive, collected = new Map()) => {
|
121
|
-
(0, graphql_1.visit)(selectable, {
|
122
|
-
FragmentSpread(spread) {
|
123
|
-
const fragmentName = spread.name.value;
|
124
|
-
const [fragment] = getFragment(fragmentName);
|
125
|
-
if (!fragment) {
|
126
|
-
utils_js_1.logger.warn(`Unable to locate fragment named "${fragmentName}", please make sure it's loaded using "parserOptions.operations"`);
|
127
|
-
return;
|
128
|
-
}
|
129
|
-
if (!collected.has(fragmentName)) {
|
130
|
-
collected.set(fragmentName, fragment.document);
|
131
|
-
if (recursive) {
|
132
|
-
collectFragments(fragment.document, recursive, collected);
|
133
|
-
}
|
134
|
-
}
|
135
|
-
},
|
136
|
-
});
|
137
|
-
return collected;
|
138
|
-
};
|
139
|
-
const siblingOperations = {
|
140
|
-
available: true,
|
141
|
-
getFragment,
|
142
|
-
getFragments,
|
143
|
-
getFragmentByType: typeName => getFragments().filter(f => { var _a, _b; return ((_b = (_a = f.document.typeCondition) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.value) === typeName; }),
|
144
|
-
getFragmentsInUse: (selectable, recursive = true) => Array.from(collectFragments(selectable, recursive).values()),
|
145
|
-
getOperation: name => getOperations().filter(o => { var _a; return ((_a = o.document.name) === null || _a === void 0 ? void 0 : _a.value) === name; }),
|
146
|
-
getOperations,
|
147
|
-
getOperationByType: type => getOperations().filter(o => o.document.operation === type),
|
148
|
-
};
|
149
|
-
siblingOperationsCache.set(siblings, siblingOperations);
|
150
|
-
return siblingOperations;
|
151
|
-
}
|
152
49
|
exports.getDocuments = getDocuments;
|
package/cjs/graphql-config.js
CHANGED
@@ -33,7 +33,7 @@ function loadGraphQLConfig(options) {
|
|
33
33
|
? { projects: options.projects }
|
34
34
|
: {
|
35
35
|
schema: (options.schema || ''),
|
36
|
-
documents: options.documents
|
36
|
+
documents: options.documents,
|
37
37
|
extensions: options.extensions,
|
38
38
|
include: options.include,
|
39
39
|
exclude: options.exclude,
|
package/cjs/parser.js
CHANGED
@@ -5,16 +5,18 @@ const tslib_1 = require("tslib");
|
|
5
5
|
const utils_1 = require("@graphql-tools/utils");
|
6
6
|
const debug_1 = tslib_1.__importDefault(require("debug"));
|
7
7
|
const graphql_1 = require("graphql");
|
8
|
-
const documents_js_1 = require("./documents.js");
|
9
8
|
const index_js_1 = require("./estree-converter/index.js");
|
10
9
|
const graphql_config_js_1 = require("./graphql-config.js");
|
11
10
|
const schema_js_1 = require("./schema.js");
|
11
|
+
const siblings_js_1 = require("./siblings.js");
|
12
12
|
const utils_js_1 = require("./utils.js");
|
13
13
|
const debug = (0, debug_1.default)('graphql-eslint:parser');
|
14
14
|
debug('cwd %o', utils_js_1.CWD);
|
15
15
|
function parseForESLint(code, options) {
|
16
16
|
try {
|
17
17
|
const { filePath } = options;
|
18
|
+
// TODO: remove in graphql-eslint v4
|
19
|
+
options.documents || (options.documents = options.operations);
|
18
20
|
// First parse code from file, in case of syntax error do not try load schema,
|
19
21
|
// documents or even graphql-config instance
|
20
22
|
const { document } = (0, utils_1.parseGraphQLSDL)(filePath, code, {
|
@@ -24,12 +26,16 @@ function parseForESLint(code, options) {
|
|
24
26
|
const gqlConfig = (0, graphql_config_js_1.loadGraphQLConfig)(options);
|
25
27
|
const realFilepath = filePath.replace(utils_js_1.VIRTUAL_DOCUMENT_REGEX, '');
|
26
28
|
const project = gqlConfig.getProjectForFile(realFilepath);
|
27
|
-
const schema =
|
29
|
+
const schema = project
|
30
|
+
? (0, schema_js_1.getSchema)(project, options.schemaOptions)
|
31
|
+
: typeof options.schema === 'string'
|
32
|
+
? (0, graphql_1.buildSchema)(options.schema)
|
33
|
+
: null;
|
28
34
|
const rootTree = (0, index_js_1.convertToESTree)(document, schema instanceof graphql_1.GraphQLSchema ? schema : undefined);
|
29
35
|
return {
|
30
36
|
services: {
|
31
37
|
schema,
|
32
|
-
siblingOperations: (0,
|
38
|
+
siblingOperations: (0, siblings_js_1.getSiblings)(project, options.documents),
|
33
39
|
},
|
34
40
|
ast: {
|
35
41
|
comments: (0, index_js_1.extractComments)(document.loc),
|
package/cjs/rules/alphabetize.js
CHANGED
@@ -87,7 +87,7 @@ exports.rule = {
|
|
87
87
|
docs: {
|
88
88
|
category: ['Schema', 'Operations'],
|
89
89
|
description: 'Enforce arrange in alphabetical order for type fields, enum values, input object fields, operation selections and more.',
|
90
|
-
url: `https://
|
90
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
91
91
|
examples: [
|
92
92
|
{
|
93
93
|
title: 'Incorrect',
|
@@ -45,7 +45,7 @@ exports.rule = {
|
|
45
45
|
],
|
46
46
|
description: 'Require all comments to follow the same style (either block or inline).',
|
47
47
|
category: 'Schema',
|
48
|
-
url: 'https://
|
48
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/description-style',
|
49
49
|
recommended: true,
|
50
50
|
},
|
51
51
|
schema,
|
@@ -116,7 +116,7 @@ const validationToRule = ({ ruleId, ruleName, getDocumentNode, schema = [], hasD
|
|
116
116
|
recommended: true,
|
117
117
|
...docs,
|
118
118
|
graphQLJSRuleName: ruleName,
|
119
|
-
url: `https://
|
119
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${ruleId}`,
|
120
120
|
description: `${docs.description}\n> This rule is a wrapper around a \`graphql-js\` validation function.`,
|
121
121
|
},
|
122
122
|
schema,
|
package/cjs/rules/input-name.js
CHANGED
@@ -12,7 +12,7 @@ const schema = {
|
|
12
12
|
checkInputType: {
|
13
13
|
type: 'boolean',
|
14
14
|
default: false,
|
15
|
-
description: 'Check that the input type name follows the convention
|
15
|
+
description: 'Check that the input type name follows the convention \\<mutationName>Input',
|
16
16
|
},
|
17
17
|
caseSensitiveInputType: {
|
18
18
|
type: 'boolean',
|
@@ -44,7 +44,7 @@ exports.rule = {
|
|
44
44
|
docs: {
|
45
45
|
description: 'Require mutation argument to be always called "input" and input type to be called Mutation name + "Input".\nUsing the same name for all input parameters will make your schemas easier to consume and more predictable. Using the same name as mutation for InputType will make it easier to find mutations that InputType belongs to.',
|
46
46
|
category: 'Schema',
|
47
|
-
url: 'https://
|
47
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/input-name',
|
48
48
|
examples: [
|
49
49
|
{
|
50
50
|
title: 'Incorrect',
|
@@ -56,7 +56,7 @@ exports.rule = {
|
|
56
56
|
`,
|
57
57
|
},
|
58
58
|
{
|
59
|
-
title: 'Correct (with checkInputType)',
|
59
|
+
title: 'Correct (with `checkInputType`)',
|
60
60
|
usage: [{ checkInputType: true }],
|
61
61
|
code: /* GraphQL */ `
|
62
62
|
type Mutation {
|
@@ -65,7 +65,7 @@ exports.rule = {
|
|
65
65
|
`,
|
66
66
|
},
|
67
67
|
{
|
68
|
-
title: 'Correct (without checkInputType)',
|
68
|
+
title: 'Correct (without `checkInputType`)',
|
69
69
|
usage: [{ checkInputType: false }],
|
70
70
|
code: /* GraphQL */ `
|
71
71
|
type Mutation {
|
@@ -29,7 +29,7 @@ exports.rule = {
|
|
29
29
|
docs: {
|
30
30
|
category: 'Operations',
|
31
31
|
description: 'Require queries, mutations, subscriptions or fragments to be located in separate files.',
|
32
|
-
url: `https://
|
32
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
33
33
|
examples: [
|
34
34
|
{
|
35
35
|
title: 'Incorrect',
|
@@ -1,7 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.rule = void 0;
|
4
|
-
const fs_1 = require("fs");
|
5
4
|
const path_1 = require("path");
|
6
5
|
const graphql_1 = require("graphql");
|
7
6
|
const utils_js_1 = require("../utils.js");
|
@@ -57,7 +56,7 @@ exports.rule = {
|
|
57
56
|
docs: {
|
58
57
|
category: 'Operations',
|
59
58
|
description: 'This rule allows you to enforce that the file name should match the operation name.',
|
60
|
-
url: 'https://
|
59
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/match-document-filename',
|
61
60
|
examples: [
|
62
61
|
{
|
63
62
|
title: 'Correct',
|
@@ -169,7 +168,7 @@ exports.rule = {
|
|
169
168
|
fileExtension: null,
|
170
169
|
};
|
171
170
|
const filePath = context.getFilename();
|
172
|
-
const isVirtualFile =
|
171
|
+
const isVirtualFile = utils_js_1.VIRTUAL_DOCUMENT_REGEX.test(filePath);
|
173
172
|
if (process.env.NODE_ENV !== 'test' && isVirtualFile) {
|
174
173
|
// Skip validation for code files
|
175
174
|
return {};
|
@@ -100,7 +100,7 @@ exports.rule = {
|
|
100
100
|
description: 'Require names to follow specified conventions.',
|
101
101
|
category: ['Schema', 'Operations'],
|
102
102
|
recommended: true,
|
103
|
-
url: 'https://
|
103
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/naming-convention',
|
104
104
|
examples: [
|
105
105
|
{
|
106
106
|
title: 'Incorrect',
|
@@ -12,7 +12,7 @@ exports.rule = {
|
|
12
12
|
category: 'Operations',
|
13
13
|
description: 'Require name for your GraphQL operations. This is useful since most GraphQL client libraries are using the operation name for caching purposes.',
|
14
14
|
recommended: true,
|
15
|
-
url: `https://
|
15
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
16
16
|
examples: [
|
17
17
|
{
|
18
18
|
title: 'Incorrect',
|
@@ -7,7 +7,7 @@ exports.rule = {
|
|
7
7
|
type: 'suggestion',
|
8
8
|
hasSuggestions: true,
|
9
9
|
docs: {
|
10
|
-
url: 'https://
|
10
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/no-case-insensitive-enum-values-duplicates',
|
11
11
|
category: 'Schema',
|
12
12
|
recommended: true,
|
13
13
|
description: 'Disallow case-insensitive enum values duplicates.',
|
@@ -11,7 +11,7 @@ exports.rule = {
|
|
11
11
|
docs: {
|
12
12
|
category: 'Operations',
|
13
13
|
description: 'Enforce that deprecated fields or enum values are not in use by operations.',
|
14
|
-
url: `https://
|
14
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
15
15
|
requiresSchema: true,
|
16
16
|
examples: [
|
17
17
|
{
|
@@ -10,7 +10,7 @@ exports.rule = {
|
|
10
10
|
docs: {
|
11
11
|
description: 'Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.',
|
12
12
|
category: 'Operations',
|
13
|
-
url: `https://
|
13
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
14
14
|
recommended: true,
|
15
15
|
examples: [
|
16
16
|
{
|
@@ -14,7 +14,7 @@ exports.rule = {
|
|
14
14
|
docs: {
|
15
15
|
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.',
|
16
16
|
category: 'Schema',
|
17
|
-
url: 'https://
|
17
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/no-hashtag-description',
|
18
18
|
examples: [
|
19
19
|
{
|
20
20
|
title: 'Incorrect',
|
@@ -11,7 +11,7 @@ exports.rule = {
|
|
11
11
|
docs: {
|
12
12
|
category: 'Operations',
|
13
13
|
description: 'Disallow fragments that are used only in one place.',
|
14
|
-
url: `https://
|
14
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
15
15
|
examples: [
|
16
16
|
{
|
17
17
|
title: 'Incorrect',
|