@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/docs/deprecated-rules.md
CHANGED
@@ -1,24 +1 @@
|
|
1
|
-
|
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
|
10
|
-
[`no-scalar-result-type-on-mutation`](rules/no-scalar-result-type-on-mutation.md).
|
11
|
-
|
12
|
-
## avoid-typename-prefix
|
13
|
-
|
14
|
-
This rule was renamed to [`no-typename-prefix`](rules/no-typename-prefix.md).
|
15
|
-
|
16
|
-
## avoid-operation-name-prefix
|
17
|
-
|
18
|
-
This rule was removed because the same things can be validated using
|
19
|
-
[`naming-convention`](rules/naming-convention.md).
|
20
|
-
|
21
|
-
## no-operation-name-suffix
|
22
|
-
|
23
|
-
This rule was removed because the same things can be validated using
|
24
|
-
[`naming-convention`](rules/naming-convention.md).
|
1
|
+
website/src/pages/rules/deprecated-rules.mdx
|
package/docs/parser-options.md
CHANGED
@@ -1,107 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
## `graphQLParserOptions`
|
4
|
-
|
5
|
-
With this configuration, you can specify custom configurations for GraphQL's `parse` method. By
|
6
|
-
default, `graphql-eslint` parser just adds `noLocation: false` to make sure all parsed AST has
|
7
|
-
`location` set, since we need this for tokenizing and for converting the GraphQL AST into ESTree.
|
8
|
-
|
9
|
-
You can find the
|
10
|
-
[complete set of options for this object here](https://github.com/graphql/graphql-js/blob/6e48d16f92b9a6df8638b1486354c6be2537033b/src/language/parser.ts#L73)
|
11
|
-
|
12
|
-
## `skipGraphQLConfig`
|
13
|
-
|
14
|
-
If you are using [`graphql-config`](https://graphql-config.com) in your project, the parser will
|
15
|
-
automatically use that to load your default GraphQL schema.
|
16
|
-
|
17
|
-
You can disable this behaviour using `skipGraphQLConfig: true` in the `parserOptions`:
|
18
|
-
|
19
|
-
```json
|
20
|
-
{
|
21
|
-
"parserOptions": {
|
22
|
-
"skipGraphQLConfig": true
|
23
|
-
}
|
24
|
-
}
|
25
|
-
```
|
26
|
-
|
27
|
-
## `schema`
|
28
|
-
|
29
|
-
You can specify `parserOptions.schema` to load your GraphQL schema. The parser uses `graphql-tools`
|
30
|
-
and it's loaders, that means you can either specify a URL, a path to a local `.json` (introspection)
|
31
|
-
file, or a path to a local `.graphql` file(s). You can also use Glob expressions to load multiple
|
32
|
-
files.
|
33
|
-
|
34
|
-
Here are a few examples for a valid setup:
|
35
|
-
|
36
|
-
```json
|
37
|
-
{
|
38
|
-
"parserOptions": {
|
39
|
-
"schema": "./schema.graphql"
|
40
|
-
}
|
41
|
-
}
|
42
|
-
```
|
43
|
-
|
44
|
-
```json
|
45
|
-
{
|
46
|
-
"parserOptions": {
|
47
|
-
"schema": "./schema.json"
|
48
|
-
}
|
49
|
-
}
|
50
|
-
```
|
51
|
-
|
52
|
-
```json
|
53
|
-
{
|
54
|
-
"parserOptions": {
|
55
|
-
"schema": "http://my-server/graphql"
|
56
|
-
}
|
57
|
-
}
|
58
|
-
```
|
59
|
-
|
60
|
-
```json
|
61
|
-
{
|
62
|
-
"parserOptions": {
|
63
|
-
"schema": "./src/**/*.graphql"
|
64
|
-
}
|
65
|
-
}
|
66
|
-
```
|
67
|
-
|
68
|
-
```json
|
69
|
-
{
|
70
|
-
"parserOptions": {
|
71
|
-
"schema": ["src/schema-a.graphql", "src/schema-b.graphql", "src/schema-c.graphql"]
|
72
|
-
}
|
73
|
-
}
|
74
|
-
```
|
75
|
-
|
76
|
-
## `schemaOptions`
|
77
|
-
|
78
|
-
If you wish to send additional configuration for the `graphql-tools` loaders that loads your schema,
|
79
|
-
you can specify `schemaOptions` object:
|
80
|
-
|
81
|
-
```json
|
82
|
-
{
|
83
|
-
"parserOptions": {
|
84
|
-
"schema": "http://my-server/graphql",
|
85
|
-
"schemaOptions": {
|
86
|
-
"headers": {
|
87
|
-
"Authorization": "Bearer MY_TOKEN"
|
88
|
-
}
|
89
|
-
}
|
90
|
-
}
|
91
|
-
}
|
92
|
-
```
|
93
|
-
|
94
|
-
```json
|
95
|
-
{
|
96
|
-
"parserOptions": {
|
97
|
-
"schema": "./src/**/*.graphql",
|
98
|
-
"schemaOptions": {
|
99
|
-
"assumeValid": true
|
100
|
-
}
|
101
|
-
}
|
102
|
-
}
|
103
|
-
```
|
104
|
-
|
105
|
-
> The configuration here is flexible, and will be sent to `graphql-tools` and it's loaders. So
|
106
|
-
> depends on the schema source, the options may vary.
|
107
|
-
> [You can read more about these loaders and their configuration here](https://graphql-tools.com/docs/api/interfaces/loaders_graphql_file_src.GraphQLFileLoaderOptions#properties).
|
1
|
+
website/src/pages/docs/getting-started/parser-options.mdx
|
package/docs/parser.md
CHANGED
@@ -1,67 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
The `graphql-eslint` parser is works in the following way:
|
4
|
-
|
5
|
-
1. Loads all relevant GraphQL code using ESLint core (either from `.graphql` files, or using
|
6
|
-
[ESLint `processor`](https://eslint.org/docs/developer-guide/working-with-plugins#processors-in-plugins)
|
7
|
-
to find in code-files).
|
8
|
-
1. Is uses `graphql-js` (and `graphql-tools`) to parse the found string into a `DocumentNode`.
|
9
|
-
1. Extracts all comments (marked as `# ...`) from the parsed AST, and provides to ESLint as
|
10
|
-
directives hints.
|
11
|
-
1. If `graphql-config` is used, or `schema` field is provided, the schema is being loaded and
|
12
|
-
provided to the rules using `parserServices`.
|
13
|
-
1. Converts the `DocumentNode` to ESTree structure (and enrich the nodes with `typeInfo`, if schema
|
14
|
-
is loaded).
|
15
|
-
|
16
|
-
## ESTree Conversion
|
17
|
-
|
18
|
-
The GraphQL AST structure is very similar to ESTree structure, but there are a few differences that
|
19
|
-
the `parser` does.
|
20
|
-
|
21
|
-
Here's a list of changes that the parser performs, in order to make the GraphQL AST compatible with
|
22
|
-
ESTree:
|
23
|
-
|
24
|
-
---
|
25
|
-
|
26
|
-
**Problem**: GraphQL uses `kind` field to define the kind of the AST node, while ESTree uses `type`.
|
27
|
-
|
28
|
-
**Solution**: The parser adds `type` field on each node, and just copies the value from `kind`
|
29
|
-
field.
|
30
|
-
|
31
|
-
---
|
32
|
-
|
33
|
-
**Problem**: Some GraphQL AST nodes are using `type` field (which conflicts with the ESTree kind).
|
34
|
-
|
35
|
-
**Solution**: AST nodes that has `type` field are being transformed, and the `type` field changes to
|
36
|
-
`gqlType`.
|
37
|
-
|
38
|
-
---
|
39
|
-
|
40
|
-
**Problem**: GraphQL AST structure allows circular JSON links (while ESTree might fail on
|
41
|
-
`Maximum call stack exceeded`).
|
42
|
-
|
43
|
-
**Solution**: The parser removes circular JSONs (specifically around GraphQL `Location` and the
|
44
|
-
`Lexer`)
|
45
|
-
|
46
|
-
---
|
47
|
-
|
48
|
-
**Problem**: GraphQL uses `location` field to store the AST locations, while ESTree also uses it in
|
49
|
-
a different structure.
|
50
|
-
|
51
|
-
**Solution**: The parser creates a new `location` field that is compatible with ESTree.
|
52
|
-
|
53
|
-
### Loading GraphQL Schema
|
54
|
-
|
55
|
-
If you are using [`graphql-config`](https://graphql-config.com) in your project, the parser will
|
56
|
-
automatically use that to load your default GraphQL schema (you can disable this behaviour using
|
57
|
-
`skipGraphQLConfig: true` in the `parserOptions`).
|
58
|
-
|
59
|
-
If you are not using `graphql-config`, you can specify `parserOptions.schema` to load your GraphQL
|
60
|
-
schema. The parser uses `graphql-tools` and it's loaders, that means you can either specify a URL, a
|
61
|
-
path to a local `.json` (introspection) file, or a path to a local `.graphql` file(s). You can also
|
62
|
-
use Glob expressions to load multiple files.
|
63
|
-
|
64
|
-
[You can find more detail on the `parserOptions` config here](parser-options.md)
|
65
|
-
|
66
|
-
Providing the schema will make sure that rules that needs it will be able to access it, and it
|
67
|
-
enriches every converted AST node with `typeInfo`.
|
1
|
+
website/src/pages/docs/getting-started/parser.mdx
|
package/esm/documents.js
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
import { resolve } from 'path';
|
2
2
|
import debugFactory from 'debug';
|
3
3
|
import fg from 'fast-glob';
|
4
|
-
import { Kind, visit, } from 'graphql';
|
5
4
|
import { ModuleCache } from './cache.js';
|
6
|
-
import { logger } from './utils.js';
|
7
5
|
const debug = debugFactory('graphql-eslint:operations');
|
6
|
+
const operationsCache = new ModuleCache();
|
8
7
|
const handleVirtualPath = (documents) => {
|
9
8
|
const filepathMap = Object.create(null);
|
10
9
|
return documents.map(source => {
|
@@ -21,9 +20,7 @@ const handleVirtualPath = (documents) => {
|
|
21
20
|
};
|
22
21
|
});
|
23
22
|
};
|
24
|
-
const
|
25
|
-
const siblingOperationsCache = new Map();
|
26
|
-
const getSiblings = (project) => {
|
23
|
+
export const getDocuments = (project) => {
|
27
24
|
const documentsKey = project.documents;
|
28
25
|
if (!documentsKey) {
|
29
26
|
return [];
|
@@ -45,103 +42,3 @@ const getSiblings = (project) => {
|
|
45
42
|
}
|
46
43
|
return siblings;
|
47
44
|
};
|
48
|
-
export function getDocuments(project) {
|
49
|
-
const siblings = getSiblings(project);
|
50
|
-
if (siblings.length === 0) {
|
51
|
-
let printed = false;
|
52
|
-
const noopWarn = () => {
|
53
|
-
if (!printed) {
|
54
|
-
logger.warn('getSiblingOperations was called without any operations. Make sure to set "parserOptions.operations" to make this feature available!');
|
55
|
-
printed = true;
|
56
|
-
}
|
57
|
-
return [];
|
58
|
-
};
|
59
|
-
return {
|
60
|
-
available: false,
|
61
|
-
getFragment: noopWarn,
|
62
|
-
getFragments: noopWarn,
|
63
|
-
getFragmentByType: noopWarn,
|
64
|
-
getFragmentsInUse: noopWarn,
|
65
|
-
getOperation: noopWarn,
|
66
|
-
getOperations: noopWarn,
|
67
|
-
getOperationByType: noopWarn,
|
68
|
-
};
|
69
|
-
}
|
70
|
-
// Since the siblings array is cached, we can use it as cache key.
|
71
|
-
// We should get the same array reference each time we get
|
72
|
-
// to this point for the same graphql project
|
73
|
-
const value = siblingOperationsCache.get(siblings);
|
74
|
-
if (value) {
|
75
|
-
return value;
|
76
|
-
}
|
77
|
-
let fragmentsCache = null;
|
78
|
-
const getFragments = () => {
|
79
|
-
var _a;
|
80
|
-
if (fragmentsCache === null) {
|
81
|
-
const result = [];
|
82
|
-
for (const source of siblings) {
|
83
|
-
for (const definition of ((_a = source.document) === null || _a === void 0 ? void 0 : _a.definitions) || []) {
|
84
|
-
if (definition.kind === Kind.FRAGMENT_DEFINITION) {
|
85
|
-
result.push({
|
86
|
-
filePath: source.location,
|
87
|
-
document: definition,
|
88
|
-
});
|
89
|
-
}
|
90
|
-
}
|
91
|
-
}
|
92
|
-
fragmentsCache = result;
|
93
|
-
}
|
94
|
-
return fragmentsCache;
|
95
|
-
};
|
96
|
-
let cachedOperations = null;
|
97
|
-
const getOperations = () => {
|
98
|
-
var _a;
|
99
|
-
if (cachedOperations === null) {
|
100
|
-
const result = [];
|
101
|
-
for (const source of siblings) {
|
102
|
-
for (const definition of ((_a = source.document) === null || _a === void 0 ? void 0 : _a.definitions) || []) {
|
103
|
-
if (definition.kind === Kind.OPERATION_DEFINITION) {
|
104
|
-
result.push({
|
105
|
-
filePath: source.location,
|
106
|
-
document: definition,
|
107
|
-
});
|
108
|
-
}
|
109
|
-
}
|
110
|
-
}
|
111
|
-
cachedOperations = result;
|
112
|
-
}
|
113
|
-
return cachedOperations;
|
114
|
-
};
|
115
|
-
const getFragment = (name) => getFragments().filter(f => { var _a; return ((_a = f.document.name) === null || _a === void 0 ? void 0 : _a.value) === name; });
|
116
|
-
const collectFragments = (selectable, recursive, collected = new Map()) => {
|
117
|
-
visit(selectable, {
|
118
|
-
FragmentSpread(spread) {
|
119
|
-
const fragmentName = spread.name.value;
|
120
|
-
const [fragment] = getFragment(fragmentName);
|
121
|
-
if (!fragment) {
|
122
|
-
logger.warn(`Unable to locate fragment named "${fragmentName}", please make sure it's loaded using "parserOptions.operations"`);
|
123
|
-
return;
|
124
|
-
}
|
125
|
-
if (!collected.has(fragmentName)) {
|
126
|
-
collected.set(fragmentName, fragment.document);
|
127
|
-
if (recursive) {
|
128
|
-
collectFragments(fragment.document, recursive, collected);
|
129
|
-
}
|
130
|
-
}
|
131
|
-
},
|
132
|
-
});
|
133
|
-
return collected;
|
134
|
-
};
|
135
|
-
const siblingOperations = {
|
136
|
-
available: true,
|
137
|
-
getFragment,
|
138
|
-
getFragments,
|
139
|
-
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; }),
|
140
|
-
getFragmentsInUse: (selectable, recursive = true) => Array.from(collectFragments(selectable, recursive).values()),
|
141
|
-
getOperation: name => getOperations().filter(o => { var _a; return ((_a = o.document.name) === null || _a === void 0 ? void 0 : _a.value) === name; }),
|
142
|
-
getOperations,
|
143
|
-
getOperationByType: type => getOperations().filter(o => o.document.operation === type),
|
144
|
-
};
|
145
|
-
siblingOperationsCache.set(siblings, siblingOperations);
|
146
|
-
return siblingOperations;
|
147
|
-
}
|
package/esm/graphql-config.js
CHANGED
@@ -28,7 +28,7 @@ export function loadGraphQLConfig(options) {
|
|
28
28
|
? { projects: options.projects }
|
29
29
|
: {
|
30
30
|
schema: (options.schema || ''),
|
31
|
-
documents: options.documents
|
31
|
+
documents: options.documents,
|
32
32
|
extensions: options.extensions,
|
33
33
|
include: options.include,
|
34
34
|
exclude: options.exclude,
|
package/esm/parser.js
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
import { parseGraphQLSDL } from '@graphql-tools/utils';
|
2
2
|
import debugFactory from 'debug';
|
3
|
-
import { GraphQLError, GraphQLSchema } from 'graphql';
|
4
|
-
import { getDocuments } from './documents.js';
|
3
|
+
import { buildSchema, GraphQLError, GraphQLSchema } from 'graphql';
|
5
4
|
import { convertToESTree, extractComments, extractTokens } from './estree-converter/index.js';
|
6
5
|
import { loadGraphQLConfig } from './graphql-config.js';
|
7
6
|
import { getSchema } from './schema.js';
|
7
|
+
import { getSiblings } from './siblings.js';
|
8
8
|
import { CWD, VIRTUAL_DOCUMENT_REGEX } from './utils.js';
|
9
9
|
const debug = debugFactory('graphql-eslint:parser');
|
10
10
|
debug('cwd %o', CWD);
|
11
11
|
export function parseForESLint(code, options) {
|
12
12
|
try {
|
13
13
|
const { filePath } = options;
|
14
|
+
// TODO: remove in graphql-eslint v4
|
15
|
+
options.documents || (options.documents = options.operations);
|
14
16
|
// First parse code from file, in case of syntax error do not try load schema,
|
15
17
|
// documents or even graphql-config instance
|
16
18
|
const { document } = parseGraphQLSDL(filePath, code, {
|
@@ -20,12 +22,16 @@ export function parseForESLint(code, options) {
|
|
20
22
|
const gqlConfig = loadGraphQLConfig(options);
|
21
23
|
const realFilepath = filePath.replace(VIRTUAL_DOCUMENT_REGEX, '');
|
22
24
|
const project = gqlConfig.getProjectForFile(realFilepath);
|
23
|
-
const schema =
|
25
|
+
const schema = project
|
26
|
+
? getSchema(project, options.schemaOptions)
|
27
|
+
: typeof options.schema === 'string'
|
28
|
+
? buildSchema(options.schema)
|
29
|
+
: null;
|
24
30
|
const rootTree = convertToESTree(document, schema instanceof GraphQLSchema ? schema : undefined);
|
25
31
|
return {
|
26
32
|
services: {
|
27
33
|
schema,
|
28
|
-
siblingOperations:
|
34
|
+
siblingOperations: getSiblings(project, options.documents),
|
29
35
|
},
|
30
36
|
ast: {
|
31
37
|
comments: extractComments(document.loc),
|
package/esm/rules/alphabetize.js
CHANGED
@@ -83,7 +83,7 @@ export const rule = {
|
|
83
83
|
docs: {
|
84
84
|
category: ['Schema', 'Operations'],
|
85
85
|
description: 'Enforce arrange in alphabetical order for type fields, enum values, input object fields, operation selections and more.',
|
86
|
-
url: `https://
|
86
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
87
87
|
examples: [
|
88
88
|
{
|
89
89
|
title: 'Incorrect',
|
@@ -42,7 +42,7 @@ export const rule = {
|
|
42
42
|
],
|
43
43
|
description: 'Require all comments to follow the same style (either block or inline).',
|
44
44
|
category: 'Schema',
|
45
|
-
url: 'https://
|
45
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/description-style',
|
46
46
|
recommended: true,
|
47
47
|
},
|
48
48
|
schema,
|
@@ -115,7 +115,7 @@ const validationToRule = ({ ruleId, ruleName, getDocumentNode, schema = [], hasD
|
|
115
115
|
recommended: true,
|
116
116
|
...docs,
|
117
117
|
graphQLJSRuleName: ruleName,
|
118
|
-
url: `https://
|
118
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${ruleId}`,
|
119
119
|
description: `${docs.description}\n> This rule is a wrapper around a \`graphql-js\` validation function.`,
|
120
120
|
},
|
121
121
|
schema,
|
package/esm/rules/input-name.js
CHANGED
@@ -9,7 +9,7 @@ const schema = {
|
|
9
9
|
checkInputType: {
|
10
10
|
type: 'boolean',
|
11
11
|
default: false,
|
12
|
-
description: 'Check that the input type name follows the convention
|
12
|
+
description: 'Check that the input type name follows the convention \\<mutationName>Input',
|
13
13
|
},
|
14
14
|
caseSensitiveInputType: {
|
15
15
|
type: 'boolean',
|
@@ -41,7 +41,7 @@ export const rule = {
|
|
41
41
|
docs: {
|
42
42
|
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.',
|
43
43
|
category: 'Schema',
|
44
|
-
url: 'https://
|
44
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/input-name',
|
45
45
|
examples: [
|
46
46
|
{
|
47
47
|
title: 'Incorrect',
|
@@ -53,7 +53,7 @@ export const rule = {
|
|
53
53
|
`,
|
54
54
|
},
|
55
55
|
{
|
56
|
-
title: 'Correct (with checkInputType)',
|
56
|
+
title: 'Correct (with `checkInputType`)',
|
57
57
|
usage: [{ checkInputType: true }],
|
58
58
|
code: /* GraphQL */ `
|
59
59
|
type Mutation {
|
@@ -62,7 +62,7 @@ export const rule = {
|
|
62
62
|
`,
|
63
63
|
},
|
64
64
|
{
|
65
|
-
title: 'Correct (without checkInputType)',
|
65
|
+
title: 'Correct (without `checkInputType`)',
|
66
66
|
usage: [{ checkInputType: false }],
|
67
67
|
code: /* GraphQL */ `
|
68
68
|
type Mutation {
|
@@ -26,7 +26,7 @@ export const rule = {
|
|
26
26
|
docs: {
|
27
27
|
category: 'Operations',
|
28
28
|
description: 'Require queries, mutations, subscriptions or fragments to be located in separate files.',
|
29
|
-
url: `https://
|
29
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
30
30
|
examples: [
|
31
31
|
{
|
32
32
|
title: 'Incorrect',
|
@@ -1,7 +1,6 @@
|
|
1
|
-
import { existsSync } from 'fs';
|
2
1
|
import { basename, extname } from 'path';
|
3
2
|
import { Kind } from 'graphql';
|
4
|
-
import { convertCase, REPORT_ON_FIRST_CHARACTER } from '../utils.js';
|
3
|
+
import { convertCase, REPORT_ON_FIRST_CHARACTER, VIRTUAL_DOCUMENT_REGEX, } from '../utils.js';
|
5
4
|
const MATCH_EXTENSION = 'MATCH_EXTENSION';
|
6
5
|
const MATCH_STYLE = 'MATCH_STYLE';
|
7
6
|
const CASE_STYLES = [
|
@@ -54,7 +53,7 @@ export const rule = {
|
|
54
53
|
docs: {
|
55
54
|
category: 'Operations',
|
56
55
|
description: 'This rule allows you to enforce that the file name should match the operation name.',
|
57
|
-
url: 'https://
|
56
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/match-document-filename',
|
58
57
|
examples: [
|
59
58
|
{
|
60
59
|
title: 'Correct',
|
@@ -166,7 +165,7 @@ export const rule = {
|
|
166
165
|
fileExtension: null,
|
167
166
|
};
|
168
167
|
const filePath = context.getFilename();
|
169
|
-
const isVirtualFile =
|
168
|
+
const isVirtualFile = VIRTUAL_DOCUMENT_REGEX.test(filePath);
|
170
169
|
if (process.env.NODE_ENV !== 'test' && isVirtualFile) {
|
171
170
|
// Skip validation for code files
|
172
171
|
return {};
|
@@ -97,7 +97,7 @@ export const rule = {
|
|
97
97
|
description: 'Require names to follow specified conventions.',
|
98
98
|
category: ['Schema', 'Operations'],
|
99
99
|
recommended: true,
|
100
|
-
url: 'https://
|
100
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/naming-convention',
|
101
101
|
examples: [
|
102
102
|
{
|
103
103
|
title: 'Incorrect',
|
@@ -9,7 +9,7 @@ export const rule = {
|
|
9
9
|
category: 'Operations',
|
10
10
|
description: 'Require name for your GraphQL operations. This is useful since most GraphQL client libraries are using the operation name for caching purposes.',
|
11
11
|
recommended: true,
|
12
|
-
url: `https://
|
12
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
13
13
|
examples: [
|
14
14
|
{
|
15
15
|
title: 'Incorrect',
|
@@ -4,7 +4,7 @@ export const rule = {
|
|
4
4
|
type: 'suggestion',
|
5
5
|
hasSuggestions: true,
|
6
6
|
docs: {
|
7
|
-
url: 'https://
|
7
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/no-case-insensitive-enum-values-duplicates',
|
8
8
|
category: 'Schema',
|
9
9
|
recommended: true,
|
10
10
|
description: 'Disallow case-insensitive enum values duplicates.',
|
@@ -8,7 +8,7 @@ export const rule = {
|
|
8
8
|
docs: {
|
9
9
|
category: 'Operations',
|
10
10
|
description: 'Enforce that deprecated fields or enum values are not in use by operations.',
|
11
|
-
url: `https://
|
11
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
12
12
|
requiresSchema: true,
|
13
13
|
examples: [
|
14
14
|
{
|
@@ -7,7 +7,7 @@ export const rule = {
|
|
7
7
|
docs: {
|
8
8
|
description: 'Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.',
|
9
9
|
category: 'Operations',
|
10
|
-
url: `https://
|
10
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
11
11
|
recommended: true,
|
12
12
|
examples: [
|
13
13
|
{
|
@@ -11,7 +11,7 @@ export const rule = {
|
|
11
11
|
docs: {
|
12
12
|
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.',
|
13
13
|
category: 'Schema',
|
14
|
-
url: 'https://
|
14
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/no-hashtag-description',
|
15
15
|
examples: [
|
16
16
|
{
|
17
17
|
title: 'Incorrect',
|
@@ -8,7 +8,7 @@ export const rule = {
|
|
8
8
|
docs: {
|
9
9
|
category: 'Operations',
|
10
10
|
description: 'Disallow fragments that are used only in one place.',
|
11
|
-
url: `https://
|
11
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
12
12
|
examples: [
|
13
13
|
{
|
14
14
|
title: 'Incorrect',
|
@@ -24,7 +24,7 @@ export const rule = {
|
|
24
24
|
docs: {
|
25
25
|
category: 'Schema',
|
26
26
|
description: 'Disallow using root types `mutation` and/or `subscription`.',
|
27
|
-
url: 'https://
|
27
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/no-root-type',
|
28
28
|
requiresSchema: true,
|
29
29
|
isDisabledForAllConfig: true,
|
30
30
|
examples: [
|
@@ -8,7 +8,7 @@ export const rule = {
|
|
8
8
|
docs: {
|
9
9
|
category: 'Schema',
|
10
10
|
description: 'Avoid scalar result type on mutation type to make sure to return a valid state.',
|
11
|
-
url: `https://
|
11
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
12
12
|
requiresSchema: true,
|
13
13
|
examples: [
|
14
14
|
{
|
@@ -7,7 +7,7 @@ export const rule = {
|
|
7
7
|
category: 'Schema',
|
8
8
|
description: 'Enforces users to avoid using the type name in a field name while defining your schema.',
|
9
9
|
recommended: true,
|
10
|
-
url: 'https://
|
10
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/no-typename-prefix',
|
11
11
|
examples: [
|
12
12
|
{
|
13
13
|
title: 'Incorrect',
|
@@ -89,7 +89,7 @@ export const rule = {
|
|
89
89
|
docs: {
|
90
90
|
description: 'Requires all types to be reachable at some level by root level fields.',
|
91
91
|
category: 'Schema',
|
92
|
-
url: `https://
|
92
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
93
93
|
requiresSchema: true,
|
94
94
|
examples: [
|
95
95
|
{
|
@@ -39,7 +39,7 @@ export const rule = {
|
|
39
39
|
docs: {
|
40
40
|
description: 'Requires all fields to be used at some level by siblings operations.',
|
41
41
|
category: 'Schema',
|
42
|
-
url: `https://
|
42
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
43
43
|
requiresSiblings: true,
|
44
44
|
requiresSchema: true,
|
45
45
|
isDisabledForAllConfig: true,
|
@@ -38,7 +38,7 @@ export const rule = {
|
|
38
38
|
'- `last` takes a non-negative integer',
|
39
39
|
'- `before` takes the Cursor type',
|
40
40
|
].join('\n'),
|
41
|
-
url: `https://
|
41
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
42
42
|
examples: [
|
43
43
|
{
|
44
44
|
title: 'Incorrect',
|
@@ -32,7 +32,7 @@ export const rule = {
|
|
32
32
|
'- Connection type must contain a field `edges` that return a list type that wraps an edge type',
|
33
33
|
'- Connection type must contain a field `pageInfo` that return a non-null `PageInfo` Object type',
|
34
34
|
].join('\n'),
|
35
|
-
url: 'https://
|
35
|
+
url: 'https://the-guild.dev/graphql/eslint/rules/relay-connection-types',
|
36
36
|
isDisabledForAllConfig: true,
|
37
37
|
examples: [
|
38
38
|
{
|
@@ -79,7 +79,7 @@ export const rule = {
|
|
79
79
|
"- Edge type's field `node` must implement `Node` interface _(optional)_",
|
80
80
|
'- A list type should only wrap an edge type _(optional)_',
|
81
81
|
].join('\n'),
|
82
|
-
url: `https://
|
82
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
83
83
|
isDisabledForAllConfig: true,
|
84
84
|
requiresSchema: true,
|
85
85
|
examples: [
|
@@ -18,7 +18,7 @@ export const rule = {
|
|
18
18
|
'- `PageInfo` must contain fields `hasPreviousPage` and `hasNextPage`, that return non-null Boolean',
|
19
19
|
'- `PageInfo` must contain fields `startCursor` and `endCursor`, that return either String or Scalar, which can be null if there are no results',
|
20
20
|
].join('\n'),
|
21
|
-
url: `https://
|
21
|
+
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
|
22
22
|
examples: [
|
23
23
|
{
|
24
24
|
title: 'Correct',
|