-
Notifications
You must be signed in to change notification settings - Fork 109
refactor: simplify AST converter, generate .json configs instead .ts
#822
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,15 +2,15 @@ | |
|
|
||
| To get started with your own rules, start by understanding how [ESLint custom rules works](https://eslint.org/docs/developer-guide/working-with-rules). | ||
|
|
||
| `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. | ||
| `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. | ||
|
|
||
| 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. | ||
|
|
||
| ## Getting Started | ||
|
|
||
| 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. | ||
|
|
||
| We recommend you to read the [graphql-eslint parser documentation](./parser.md) before getting started, to understand the differences between the AST structures. | ||
| We recommend you to read the [graphql-eslint parser documentation](parser.md) before getting started, to understand the differences between the AST structures. | ||
|
|
||
| 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 :) | ||
|
|
||
|
|
@@ -49,7 +49,7 @@ You can scan the `packages/plugin/src/rules` directory in this repo for referenc | |
| ## Accessing original GraphQL AST nodes | ||
|
|
||
| Since our parser converts GraphQL AST to ESTree structure, there are some minor differences in the structure of the objects. | ||
| 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)). | ||
| 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)). | ||
|
|
||
| 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. | ||
|
|
||
|
|
@@ -104,13 +104,12 @@ import { requireGraphQLSchemaFromContext } from '@graphql-eslint/eslint-plugin' | |
|
|
||
| export const rule = { | ||
| create(context) { | ||
| requireGraphQLSchemaFromContext(context) | ||
| requireGraphQLSchemaFromContext('your-rule-name', context) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo |
||
|
|
||
| return { | ||
| SelectionSet(node) { | ||
| const typeInfo = node.typeInfo() | ||
|
|
||
| if (typeInfo && typeInfo.gqlType) { | ||
| if (typeInfo.gqlType) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| console.log(`The GraphQLOutputType is: ${typeInfo.gqlType}`) | ||
| } | ||
| } | ||
|
|
@@ -119,7 +118,7 @@ export const rule = { | |
| } | ||
| ``` | ||
|
|
||
| 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. | ||
| 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. | ||
|
|
||
| ## Testing your rules | ||
|
|
||
|
|
@@ -141,7 +140,8 @@ ruleTester.runGraphQLTests('my-rule', rule, { | |
| ], | ||
| invalid: [ | ||
| { | ||
| code: 'query invalid { foo }' | ||
| code: 'query invalid { foo }', | ||
| errors: [{ message: 'Your error message.' }], | ||
| } | ||
| ] | ||
| }) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,13 +2,13 @@ | |
|
|
||
| ### `graphQLParserOptions` | ||
|
|
||
| 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. | ||
| 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. | ||
|
|
||
| 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) | ||
| 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) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed broken link with permanent link |
||
|
|
||
| ### `skipGraphQLConfig` | ||
|
|
||
| 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. | ||
| 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`: | ||
|
|
||
|
|
@@ -82,4 +82,4 @@ If you wish to send additional configuration for the `graphql-tools` loaders tha | |
| } | ||
| ``` | ||
|
|
||
| > 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). | ||
| > 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). | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed broken link |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| "parser": "@graphql-eslint/eslint-plugin", | ||
| "plugins": ["@graphql-eslint"] | ||
| } |
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| { | ||
| "extends": ["./base.json", "./operations-recommended.json"], | ||
| "rules": { | ||
| "@graphql-eslint/alphabetize": [ | ||
| "error", | ||
| { | ||
| "selections": ["OperationDefinition", "FragmentDefinition"], | ||
| "variables": ["OperationDefinition"], | ||
| "arguments": ["Field", "Directive"] | ||
| } | ||
| ], | ||
| "@graphql-eslint/match-document-filename": [ | ||
| "error", | ||
| { | ||
| "query": "kebab-case", | ||
| "mutation": "kebab-case", | ||
| "subscription": "kebab-case", | ||
| "fragment": "kebab-case" | ||
| } | ||
| ], | ||
| "@graphql-eslint/unique-fragment-name": "error", | ||
| "@graphql-eslint/unique-operation-name": "error" | ||
| } | ||
| } |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| { | ||
| "extends": "./base.json", | ||
| "rules": { | ||
| "@graphql-eslint/executable-definitions": "error", | ||
| "@graphql-eslint/fields-on-correct-type": "error", | ||
| "@graphql-eslint/fragments-on-composite-type": "error", | ||
| "@graphql-eslint/known-argument-names": "error", | ||
| "@graphql-eslint/known-directives": "error", | ||
| "@graphql-eslint/known-fragment-names": "error", | ||
| "@graphql-eslint/known-type-names": "error", | ||
| "@graphql-eslint/lone-anonymous-operation": "error", | ||
| "@graphql-eslint/naming-convention": [ | ||
| "error", | ||
| { | ||
| "VariableDefinition": "camelCase", | ||
| "OperationDefinition": { | ||
| "style": "PascalCase", | ||
| "forbiddenPrefixes": ["Query", "Mutation", "Subscription", "Get"], | ||
| "forbiddenSuffixes": ["Query", "Mutation", "Subscription"] | ||
| }, | ||
| "FragmentDefinition": { | ||
| "style": "PascalCase", | ||
| "forbiddenPrefixes": ["Fragment"], | ||
| "forbiddenSuffixes": ["Fragment"] | ||
| } | ||
| } | ||
| ], | ||
| "@graphql-eslint/no-anonymous-operations": "error", | ||
| "@graphql-eslint/no-deprecated": "error", | ||
| "@graphql-eslint/no-duplicate-fields": "error", | ||
| "@graphql-eslint/no-fragment-cycles": "error", | ||
| "@graphql-eslint/no-undefined-variables": "error", | ||
| "@graphql-eslint/no-unused-fragments": "error", | ||
| "@graphql-eslint/no-unused-variables": "error", | ||
| "@graphql-eslint/one-field-subscriptions": "error", | ||
| "@graphql-eslint/overlapping-fields-can-be-merged": "error", | ||
| "@graphql-eslint/possible-fragment-spread": "error", | ||
| "@graphql-eslint/provided-required-arguments": "error", | ||
| "@graphql-eslint/require-id-when-available": "error", | ||
| "@graphql-eslint/scalar-leafs": "error", | ||
| "@graphql-eslint/selection-set-depth": ["error", { "maxDepth": 7 }], | ||
| "@graphql-eslint/unique-argument-names": "error", | ||
| "@graphql-eslint/unique-directive-names-per-location": "error", | ||
| "@graphql-eslint/unique-input-field-names": "error", | ||
| "@graphql-eslint/unique-variable-names": "error", | ||
| "@graphql-eslint/value-literals-of-correct-type": "error", | ||
| "@graphql-eslint/variables-are-input-types": "error", | ||
| "@graphql-eslint/variables-in-allowed-position": "error" | ||
| } | ||
| } |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| { | ||
| "extends": ["./base.json", "./schema-recommended.json"], | ||
| "rules": { | ||
| "@graphql-eslint/alphabetize": [ | ||
| "error", | ||
| { | ||
| "fields": [ | ||
| "ObjectTypeDefinition", | ||
| "InterfaceTypeDefinition", | ||
| "InputObjectTypeDefinition" | ||
| ], | ||
| "values": ["EnumTypeDefinition"], | ||
| "arguments": [ | ||
| "FieldDefinition", | ||
| "Field", | ||
| "DirectiveDefinition", | ||
| "Directive" | ||
| ] | ||
| } | ||
| ], | ||
| "@graphql-eslint/input-name": "error", | ||
| "@graphql-eslint/no-scalar-result-type-on-mutation": "error", | ||
| "@graphql-eslint/require-deprecation-date": "error", | ||
| "@graphql-eslint/require-field-of-type-query-in-mutation-result": "error" | ||
| } | ||
| } |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
replaced with non-breaking space, so on mobile, this must look better
before
after