Skip to content

Commit b86425f

Browse files
authored
refactor: simplify AST converter (#822)
refactor: generate .json configs instead typescript fix links use `valueFromASTUntyped` from graphql-js don't export functions from `./estree-parser`, but export `requireGraphQLSchemaFromContext` and `requireSiblingsOperations`
1 parent 15c5bcd commit b86425f

28 files changed

+321
-409
lines changed

.eslintrc.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ module.exports = {
2222
'@typescript-eslint/no-non-null-assertion': 'off',
2323
'@typescript-eslint/explicit-function-return-type': 'off',
2424
'@typescript-eslint/ban-ts-ignore': 'off',
25-
'@typescript-eslint/ban-types': 'off',
2625
'unicorn/prefer-array-some': 'error',
2726
'unicorn/prefer-includes': 'error',
2827
'unicorn/no-useless-fallback-in-spread': 'error',

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ This project integrates GraphQL and ESLint, for a better developer experience.
99
## Key Features
1010

1111
- 🚀 Integrates with ESLint core (as a ESTree parser)
12-
- 🚀 Works on `.graphql` files, `gql` usages and `/* GraphQL */` magic comments
12+
- 🚀 Works on `.graphql` files, `gql` usages and `/* GraphQL */` magic comments
1313
- 🚀 Lints both GraphQL schema and GraphQL operations
1414
- 🚀 Extended type info for more advanced usages
1515
- 🚀 Supports ESLint directives (for example: `eslint-disable-next-line`)
@@ -189,10 +189,10 @@ See [docs/deprecated-rules.md](docs/deprecated-rules.md).
189189
<!-- prettier-ignore-start -->
190190
|Name|Description|
191191
|:-:|-|
192-
|[`schema-recommended`](packages/plugin/src/configs/schema-recommended.ts)|enables recommended rules for schema (SDL) development|
193-
|[`schema-all`](packages/plugin/src/configs/schema-all.ts)|enables all rules for schema (SDL) development, except for those that require `parserOptions.operations` option|
194-
|[`operations-recommended`](packages/plugin/src/configs/operations-recommended.ts) |enables recommended rules for consuming GraphQL (operations) development|
195-
|[`operations-all`](packages/plugin/src/configs/operations-all.ts)|enables all rules for consuming GraphQL (operations) development|
192+
|[`schema-recommended`](packages/plugin/src/configs/schema-recommended.json)|enables recommended rules for schema (SDL) development|
193+
|[`schema-all`](packages/plugin/src/configs/schema-all.json)|enables all rules for schema (SDL) development, except for those that require `parserOptions.operations` option|
194+
|[`operations-recommended`](packages/plugin/src/configs/operations-recommended.json) |enables recommended rules for consuming GraphQL (operations) development|
195+
|[`operations-all`](packages/plugin/src/configs/operations-all.json)|enables all rules for consuming GraphQL (operations) development|
196196
<!-- prettier-ignore-end -->
197197

198198
> If you are in a project that develops the GraphQL schema, you'll need `schema` rules.

docs/custom-rules.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
To get started with your own rules, start by understanding how [ESLint custom rules works](https://eslint.org/docs/developer-guide/working-with-rules).
44

5-
`graphql-eslint` converts the [GraphQL AST](https://graphql.org/graphql-js/language/) into [ESTree structure](https://github.com/estree/estree), so it allows you to easily travel the GraphQL AST tree easily.
5+
`graphql-eslint` converts the [GraphQL AST](https://graphql.org/graphql-js/language) into [ESTree structure](https://github.com/estree/estree), so it allows you to easily travel the GraphQL AST tree easily.
66

77
You can visit any GraphQL AST node in your custom rules, and report this as error. You don't need to have special handlers for code-files, since `graphql-eslint` extracts usages of `gql` and magic `/* GraphQL */` comments automatically, and runs it through the parser, and eventually it knows to adjust errors location to fit in your code files original location.
88

99
## Getting Started
1010

1111
Start by creating a [simple ESLint rule file](https://eslint.org/docs/developer-guide/working-with-rules), and choose the AST nodes you wish to visit. It can either be a [simple AST node `Kind`](https://github.com/graphql/graphql-js/blob/master/src/language/kinds.d.ts) or a complex [ESLint selector](https://eslint.org/docs/developer-guide/selectors) that allows you to travel and filter AST nodes.
1212

13-
We recommend you to read the [graphql-eslint parser documentation](./parser.md) before getting started, to understand the differences between the AST structures.
13+
We recommend you to read the [graphql-eslint parser documentation](parser.md) before getting started, to understand the differences between the AST structures.
1414

1515
The `graphql-eslint` comes with a TypeScript wrapper for ESLint rules, and provides a testkit to simplify testing process with GraphQL schemas, so you can use that by importing `GraphQLESLintRule` type. But if you wish to use JavaScript - that's fine :)
1616

@@ -49,7 +49,7 @@ You can scan the `packages/plugin/src/rules` directory in this repo for referenc
4949
## Accessing original GraphQL AST nodes
5050

5151
Since our parser converts GraphQL AST to ESTree structure, there are some minor differences in the structure of the objects.
52-
If you are using TypeScript, and you typed your rule with `GraphQLESLintRule` - you'll see that each `node` is a bit different from the AST nodes of GraphQL (you can read more about that in [graphql-eslint parser documentation](./parser.md)).
52+
If you are using TypeScript, and you typed your rule with `GraphQLESLintRule` - you'll see that each `node` is a bit different from the AST nodes of GraphQL (you can read more about that in [graphql-eslint parser documentation](parser.md)).
5353

5454
If you need access to the original GraphQL AST `node`, you can use `.rawNode()` method on each node you get from the AST structure of ESLint.
5555

@@ -104,13 +104,12 @@ import { requireGraphQLSchemaFromContext } from '@graphql-eslint/eslint-plugin'
104104

105105
export const rule = {
106106
create(context) {
107-
requireGraphQLSchemaFromContext(context)
107+
requireGraphQLSchemaFromContext('your-rule-name', context)
108108

109109
return {
110110
SelectionSet(node) {
111111
const typeInfo = node.typeInfo()
112-
113-
if (typeInfo && typeInfo.gqlType) {
112+
if (typeInfo.gqlType) {
114113
console.log(`The GraphQLOutputType is: ${typeInfo.gqlType}`)
115114
}
116115
}
@@ -119,7 +118,7 @@ export const rule = {
119118
}
120119
```
121120

122-
The structure of the return value of `.typeInfo()` is [defined here](https://github.com/dotansimha/graphql-eslint/blob/master/packages/plugin/src/estree-parser/converter.ts#L38-L46). So based on the `node` you are using, you'll get a different values on `.typeInfo()` result.
121+
The structure of the return value of `.typeInfo()` is [defined here](https://github.com/dotansimha/graphql-eslint/blob/master/packages/plugin/src/estree-parser/converter.ts#L45-L53). So based on the `node` you are using, you'll get a different values on `.typeInfo()` result.
123122

124123
## Testing your rules
125124

@@ -141,7 +140,8 @@ ruleTester.runGraphQLTests('my-rule', rule, {
141140
],
142141
invalid: [
143142
{
144-
code: 'query invalid { foo }'
143+
code: 'query invalid { foo }',
144+
errors: [{ message: 'Your error message.' }],
145145
}
146146
]
147147
})

docs/parser-options.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
### `graphQLParserOptions`
44

5-
With this configuration, you can specify custom configurations for GraphQL's `parse` method. By default, `graphql-eslint` parser just adds `noLocation: false` to make sure all parsed AST has `location` set, since we need this for tokening and for converting the GraphQL AST into ESTree.
5+
With this configuration, you can specify custom configurations for GraphQL's `parse` method. By default, `graphql-eslint` parser just adds `noLocation: false` to make sure all parsed AST has `location` set, since we need this for tokenizing and for converting the GraphQL AST into ESTree.
66

7-
You can find the [complete set of options for this object here](https://github.com/graphql/graphql-js/blob/master/src/language/parser.d.ts#L7)
7+
You can find the [complete set of options for this object here](https://github.com/graphql/graphql-js/blob/6e48d16f92b9a6df8638b1486354c6be2537033b/src/language/parser.ts#L73)
88

99
### `skipGraphQLConfig`
1010

11-
If you are using [`graphql-config`](https://graphql-config.com/) in your project, the parser will automatically use that to load your default GraphQL schema.
11+
If you are using [`graphql-config`](https://graphql-config.com) in your project, the parser will automatically use that to load your default GraphQL schema.
1212

1313
You can disable this behaviour using `skipGraphQLConfig: true` in the `parserOptions`:
1414

@@ -82,4 +82,4 @@ If you wish to send additional configuration for the `graphql-tools` loaders tha
8282
}
8383
```
8484

85-
> The configuration here is flexible, and will be sent to `graphql-tools` and it's loaders. So depends on the schema source, the options may vary. [You can read more about these loaders and their configuration here](https://www.graphql-tools.com/docs/api/interfaces/_loaders_graphql_file_src_index_.graphqlfileloaderoptions).
85+
> The configuration here is flexible, and will be sent to `graphql-tools` and it's loaders. So depends on the schema source, the options may vary. [You can read more about these loaders and their configuration here](https://graphql-tools.com/docs/api/interfaces/loaders_graphql_file_src.GraphQLFileLoaderOptions#properties).

docs/parser.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ Here's a list of changes that the parser performs, in order to make the GraphQL
4040

4141
### Loading GraphQL Schema
4242

43-
If you are using [`graphql-config`](https://graphql-config.com/) in your project, the parser will automatically use that to load your default GraphQL schema (you can disable this behaviour using `skipGraphQLConfig: true` in the `parserOptions`).
43+
If you are using [`graphql-config`](https://graphql-config.com) in your project, the parser will automatically use that to load your default GraphQL schema (you can disable this behaviour using `skipGraphQLConfig: true` in the `parserOptions`).
4444

4545
If you are not using `graphql-config`, you can specify `parserOptions.schema` to load your GraphQL schema. The parser uses `graphql-tools` and it's loaders, that means you can either specify a URL, a path to a local `.json` (introspection) file, or a path to a local `.graphql` file(s). You can also use Glob expressions to load multiple files.
4646

47-
[You can find more detail on the `parserOptions` config here](./parser-options.md)
47+
[You can find more detail on the `parserOptions` config here](parser-options.md)
4848

4949
Providing the schema will make sure that rules that needs it will be able to access it, and it enriches every converted AST node with `typeInfo`.

packages/plugin/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
},
5858
"buildOptions": {
5959
"input": "./src/index.ts",
60+
"copy": "./src/configs",
6061
"external": [
6162
"eslint",
6263
"graphql",

packages/plugin/src/configs/base.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"parser": "@graphql-eslint/eslint-plugin",
3+
"plugins": ["@graphql-eslint"]
4+
}

packages/plugin/src/configs/base.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/plugin/src/configs/index.ts

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"extends": ["./base.json", "./operations-recommended.json"],
3+
"rules": {
4+
"@graphql-eslint/alphabetize": [
5+
"error",
6+
{
7+
"selections": ["OperationDefinition", "FragmentDefinition"],
8+
"variables": ["OperationDefinition"],
9+
"arguments": ["Field", "Directive"]
10+
}
11+
],
12+
"@graphql-eslint/match-document-filename": [
13+
"error",
14+
{
15+
"query": "kebab-case",
16+
"mutation": "kebab-case",
17+
"subscription": "kebab-case",
18+
"fragment": "kebab-case"
19+
}
20+
],
21+
"@graphql-eslint/unique-fragment-name": "error",
22+
"@graphql-eslint/unique-operation-name": "error"
23+
}
24+
}

0 commit comments

Comments
 (0)