Giter Site home page Giter Site logo

eslint-plugin-graphql's Introduction

eslint-plugin-graphql

npm version Build Status Get on Slack


[2022-01-25] Note - Upcoming Deprecation Plans: We (Apollo) are working towards fully deprecating this repository. We suggest migrating to the community-supported graphql-eslint. We'll share detailed migration documentation when everything here is ready to be officially deprecated, but just a heads up in case you're planning on adopting anything here for a new project (which you still can of course if this project works for you - support for this project will be minimal however).


An ESLint plugin that checks tagged query strings inside JavaScript, or queries inside .graphql files, against a GraphQL schema.

npm install eslint-plugin-graphql

Screenshot from Atom

eslint-plugin-graphql has built-in settings for four GraphQL clients out of the box:

  1. Apollo client
  2. Relay
  3. Lokka
  4. FraQL

If you want to lint your GraphQL schema, rather than queries, check out cjoudrey/graphql-schema-linter.

Importing schema JSON

You'll need to import your introspection query result or the schema as a string in the Schema Language format. This can be done if you define your ESLint config in a JS file.

Retrieving a remote GraphQL schema

graphql-cli provides a get-schema command (in conjunction with a .graphqlconfig file) that makes retrieving remote schemas very simple.

apollo-codegen also provides an introspect-schema command that can get your remote schemas as well

Common options

All of the rules provided by this plugin have a few options in common. There are examples of how to use these with Apollo, Relay, Lokka, FraQL and literal files further down.

  • env: Import default settings for your GraphQL client. Supported values: 'apollo', 'relay', 'lokka', 'fraql' 'literal'. Defaults to 'apollo'. This is used for the slight parsing differences in the GraphQL syntax between Apollo, Relay, Lokka and FraQL as well as giving nice defaults to some other options.

  • tagName: The name of the template literal tag that this plugin should look for when searching for GraphQL queries. It has different defaults depending on the env option:

    • 'relay': 'Relay.QL'
    • 'internal': Special automatic value
    • others: 'gql', 'graphql'

You also have to specify a schema. You can either do it using one of these options:

  • schemaJson: Your schema as JSON.
  • schemaJsonFilepath: The absolute path to your schema as a .json file. (Warning: this variant is incompatible with eslint --cache.)
  • schemaString: Your schema in the Schema Language format as a string.

Alternatively, you can use a .graphqlconfig file instead of the above three options. If you do there's one more option to know about:

  • projectName: In case you specify multiple schemas in your .graphqlconfig file, choose which one to use by providing the project name here as a string.

There's an example on how to use a .graphqlconfig file further down.

Identity template literal tag

This plugin relies on GraphQL queries being prefixed with a special tag. In Relay and Apollo this is done often, but some other clients take query strings without a tag. In this case, fake-tag can be used to define an identity tag that doesn't do anything except for tell the linter this is a GraphQL query:

import gql from "fake-tag";

const QUERY_VIEWER_NAME = gql`
  query ViewerName {
    viewer {
      name
    }
  }
`;

Fake tags won’t be necessary once /* GraphQL */ comment tags are supported.

GraphQL literal files

This plugin also lints GraphQL literal files ending on .gql or .graphql. In order to do so set env to 'literal' in your .eslintrc.js and tell eslint to check these files as well.

eslint . --ext .js --ext .gql --ext .graphql

Example config for Apollo

// In a file called .eslintrc.js
module.exports = {
  parser: "babel-eslint",
  rules: {
    "graphql/template-strings": ['error', {
      // Import default settings for your GraphQL client. Supported values:
      // 'apollo', 'relay', 'lokka', 'fraql', 'literal'
      env: 'apollo',

      // Import your schema JSON here
      schemaJson: require('./schema.json'),

      // OR provide absolute path to your schema JSON (but not if using `eslint --cache`!)
      // schemaJsonFilepath: path.resolve(__dirname, './schema.json'),

      // OR provide the schema in the Schema Language format
      // schemaString: printSchema(schema),

      // tagName is gql by default
    }]
  },
  plugins: [
    'graphql'
  ]
}

Example config for Relay

// In a file called .eslintrc.js
module.exports = {
  parser: "babel-eslint",
  rules: {
    "graphql/template-strings": ['error', {
      // Import default settings for your GraphQL client. Supported values:
      // 'apollo', 'relay', 'lokka', 'fraql', 'literal'
      env: 'relay',

      // Import your schema JSON here
      schemaJson: require('./schema.json'),

      // OR provide absolute path to your schema JSON (but not if using `eslint --cache`!)
      // schemaJsonFilepath: path.resolve(__dirname, './schema.json'),

      // OR provide the schema in the Schema Language format
      // schemaString: printSchema(schema),

      // tagName is set for you to Relay.QL
    }]
  },
  plugins: [
    'graphql'
  ]
}

Example config for Lokka

// In a file called .eslintrc.js
module.exports = {
  parser: "babel-eslint",
  rules: {
    "graphql/template-strings": ['error', {
      // Import default settings for your GraphQL client. Supported values:
      // 'apollo', 'relay', 'lokka', 'fraql', 'literal'
      env: 'lokka',

      // Import your schema JSON here
      schemaJson: require('./schema.json'),

      // OR provide absolute path to your schema JSON (but not if using `eslint --cache`!)
      // schemaJsonFilepath: path.resolve(__dirname, './schema.json'),

      // OR provide the schema in the Schema Language format
      // schemaString: printSchema(schema),

      // Optional, the name of the template tag, defaults to 'gql'
      tagName: 'gql'
    }]
  },
  plugins: [
    'graphql'
  ]
}

Example config for FraQL

// In a file called .eslintrc.js
module.exports = {
  parser: "babel-eslint",
  rules: {
    "graphql/template-strings": ['error', {
      // Import default settings for your GraphQL client. Supported values:
      // 'apollo', 'relay', 'lokka', 'fraql', 'literal'
      env: 'fraql',

      // Import your schema JSON here
      schemaJson: require('./schema.json'),

      // OR provide absolute path to your schema JSON
      // schemaJsonFilepath: path.resolve(__dirname, './schema.json'),

      // OR provide the schema in the Schema Language format
      // schemaString: printSchema(schema),

      // Optional, the name of the template tag, defaults to 'gql'
      tagName: 'gql'
    }]
  },
  plugins: [
    'graphql'
  ]
}

Example config for literal graphql files

// In a file called .eslintrc.js
module.exports = {
  parser: "babel-eslint",
  rules: {
    "graphql/template-strings": ['error', {
      // Import default settings for your GraphQL client. Supported values:
      // 'apollo', 'relay', 'lokka', 'fraql', 'literal'
      env: 'literal',

      // Import your schema JSON here
      schemaJson: require('./schema.json'),

      // OR provide absolute path to your schema JSON (but not if using `eslint --cache`!)
      // schemaJsonFilepath: path.resolve(__dirname, './schema.json'),

      // OR provide the schema in the Schema Language format
      // schemaString: printSchema(schema),

      // tagName is set automatically
    }]
  },
  plugins: [
    'graphql'
  ]
}

Additional Schemas or Tags

This plugin can be used to validate against multiple schemas by identifying them with different tags. This is useful for applications interacting with multiple GraphQL systems. Additional schemas can simply be appended to the options list:

module.exports = {
  parser: "babel-eslint",
  rules: {
    "graphql/template-strings": ['error', {
      env: 'apollo',
      tagName: 'FirstGQL',
      schemaJson: require('./schema-first.json')
    }, {
      env: 'relay',
      tagName: 'SecondGQL',
      schemaJson: require('./schema-second.json')
    }]
  },
  plugins: [
    'graphql'
  ]
}

Example config when using .graphqlconfig

If you have .graphqlconfig file in the root of your repo you can omit schema-related properties (schemaJson, schemaJsonFilepath and schemaString) from rule config.

// In a file called .eslintrc.js
module.exports = {
  parser: "babel-eslint",
  rules: {
    "graphql/template-strings": ['error', {
      // Import default settings for your GraphQL client. Supported values:
      // 'apollo', 'relay', 'lokka', 'fraql', 'literal'
      env: 'literal'
      // no need to specify schema here, it will be automatically determined using .graphqlconfig
    }]
  },
  plugins: [
    'graphql'
  ]
}

In case you use additional schemas, specify projectName from .graphqlconfig for each tagName:

module.exports = {
  parser: "babel-eslint",
  rules: {
    "graphql/template-strings": ['error', {
      env: 'apollo',
      tagName: 'FirstGQL',
      projectName: 'FirstGQLProject'
    }, {
      env: 'relay',
      tagName: 'SecondGQL',
      projectName: 'SecondGQLProject'
    }]
  },
  plugins: [
    'graphql'
  ]
}

Selecting Validation Rules

GraphQL validation rules can be configured in the eslint rule configuration using the validators option. The default selection depends on the env setting. If no env is specified, all rules are enabled by default.

The validators setting can be set either to a list of specific validator names or to the special value "all".

module.exports = {
  parser: "babel-eslint",
  rules: {
    "graphql/template-strings": ['error', {
      env: 'apollo',
      validators: 'all',
      tagName: 'FirstGQL',
      schemaJson: require('./schema-first.json')
    }, {
      validators: ['FieldsOnCorrectType'],
      tagName: 'SecondGQL',
      schemaJson: require('./schema-second.json')
    }]
  },
  plugins: [
    'graphql'
  ]
}

The full list of available validators is:

  • ExecutableDefinitions
  • FieldsOnCorrectType
  • FragmentsOnCompositeTypes
  • KnownArgumentNames
  • KnownDirectives (disabled by default in relay)
  • KnownFragmentNames (disabled by default in all envs)
  • KnownTypeNames
  • LoneAnonymousOperation
  • NoFragmentCycles
  • NoUndefinedVariables (disabled by default in relay)
  • NoUnusedFragments (disabled by default in all envs)
  • NoUnusedVariables
  • OverlappingFieldsCanBeMerged
  • PossibleFragmentSpreads
  • ProvidedRequiredArguments (disabled by default in relay)
  • ScalarLeafs (disabled by default in relay)
  • SingleFieldSubscriptions
  • UniqueArgumentNames
  • UniqueDirectivesPerLocation
  • UniqueFragmentNames
  • UniqueInputFieldNames
  • UniqueOperationNames
  • UniqueVariableNames
  • ValuesOfCorrectType
  • VariablesAreInputTypes
  • VariablesDefaultValueAllowed
  • VariablesInAllowedPosition

Named Operations Validation Rule

The Named Operation rule validates that all operations are named. Naming operations is valuable for including in server-side logs and debugging.

Pass

query FetchUsername {
  viewer {
    name
  }
}

Fail

query {
  viewer {
    name
  }
}

The rule is defined as graphql/named-operations.

// In a file called .eslintrc.js
module.exports = {
  parser: "babel-eslint",
  rules: {
    "graphql/template-strings": ['error', {
      env: 'apollo',
      schemaJson: require('./schema.json'),
    }],
    "graphql/named-operations": ['warn', {
      schemaJson: require('./schema.json'),
    }],
  },
  plugins: [
    'graphql'
  ]
}

Required Fields Validation Rule

The Required Fields rule validates that any specified required field is part of the query, but only if that field is available in schema. This is useful to ensure that query results are cached properly in the client.

Pass

// 'uuid' required and present in the schema

schema {
  query {
    viewer {
      name
      uuid
    }
  }
}

query ViewerName {
  viewer {
    name
    uuid
  }
}

Pass

// 'uuid' usually required but not present in the schema here

schema {
  query {
    viewer {
      name
    }
  }
}

query ViewerName {
  viewer {
    name
  }
}

Fail

// 'uuid' required and present in the schema

schema {
  query {
    viewer {
      uuid
      name
    }
  }
}

query ViewerName {
  viewer {
    name
  }
}

The rule is defined as graphql/required-fields and requires the requiredFields option.

// In a file called .eslintrc.js
module.exports = {
  rules: {
    'graphql/required-fields': [
      'error',
      {
        env: 'apollo',
        schemaJsonFilepath: path.resolve(__dirname, './schema.json'),
        requiredFields: ['uuid'],
      },
    ],
  },
  plugins: [
    'graphql'
  ]
}

Capitalization of a first letter of a Type name

This rule enforces that first letter of types is capitalized

Pass

query {
  someUnion {
    ... on SomeType {
      someField
    }
  }
}

Fail

query {
  someUnion {
    ... on someType {
      someField
    }
  }
}

The rule is defined as graphql/capitalized-type-name.

// In a file called .eslintrc.js
module.exports = {
  parser: "babel-eslint",
  rules: {
    "graphql/template-strings": ['error', {
      env: 'apollo',
      schemaJson: require('./schema.json'),
    }],
    "graphql/capitalized-type-name": ['warn', {
      schemaJson: require('./schema.json'),
    }],
  },
  plugins: [
    'graphql'
  ]
}

No Deprecated Fields Validation Rule

The No Deprecated Fields rule validates that no deprecated fields are part of the query. This is useful to discover fields that have been marked as deprecated and shouldn't be used.

Fail

// 'id' requested and marked as deprecated in the schema

schema {
  query {
    viewer {
      id: Int @deprecated(reason: "Use the 'uuid' field instead")
      uuid: String
    }
  }
}

query ViewerName {
  viewer {
    id
  }
}

The rule is defined as graphql/no-deprecated-fields.

// In a file called .eslintrc.js
module.exports = {
  rules: {
    'graphql/no-deprecated-fields': [
      'error',
      {
        env: 'relay',
        schemaJson: require('./schema.json')
      },
    ],
  },
  plugins: [
    'graphql'
  ]
}

eslint-plugin-graphql's People

Contributors

abernix avatar benjie avatar gauravmk avatar greenkeeper[bot] avatar gregberge avatar helfer avatar henryqdineen avatar hwillson avatar jaydenseric avatar jnwng avatar jonbretman avatar jtmthf avatar kamilkisiela avatar koddsson avatar lennyburdette avatar lydell avatar mattbretl avatar nodkz avatar renovate-bot avatar renovate[bot] avatar respectthecode avatar romanhotsiy avatar rwe avatar sashko-stripe avatar spyl94 avatar staylor avatar stefanorg avatar stevehollaar avatar stubailo avatar vitorbal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eslint-plugin-graphql's Issues

Linting schemas, not just queries

I'm wondering if the plugin could be used for linting the server-side code too. Let's say I have src/schema.js in my super-cool-api project that looks like this:

export default /* GraphQL */`
enum Episode { NEWHOPE, EMPIRE, JEDI }

interface Character {
  id: String!
  name: String
  friends: [Character]
  appearsIn: [Episode]
}

# ...

type Query {
  hero(episode: Episode): Character
  human(id: String!): Human
  droid(id: String!): Droid
}

# ...
`;

/* GraphQL */ just helps Atom's language-babel plugin highlight my code correctly:

screen shot 2016-11-29 at 16 33 53
screen shot 2016-11-29 at 16 33 37

What would be pretty a useful thing to have is some sort of a feedback for things like a missing { or an unnecessary comma. I don't think there is an easy way to go further because the schema may be split between the files, etc. /* GraphQL */ can work as trigger the check.

How do you guys lint in such cases? How feasible would it be to adopt eslint-plugin-graphql to this?

Double underscores in schema field names causing some grief

We have a few fields in our schema that start with a double underscore. One such example is a __cost field, which we use to enforce query limits. This causes an error with regards to it being named with a double underscore, and there doesn't appear to be any validation setting that can be passed in to turn this off.

Error message:

Name "__cost" must not begin with "__", which is reserved by GraphQL introspection. In a future release of graphql this will become a hard error.

Relevant slice of our schema:

...
{
    "name": "__cost",
    "description": null,
    "args": [],
    "type": {
        "kind": "SCALAR",
        "name": "JSONObject",
        "ofType": null
    },
    "isDeprecated": false,
    "deprecationReason": null
}
...

Would be nice to either turn this off or be able to pass a validation flag or something. It appears that the function where this error is originating from in the graphql-js package already accepts an isIntrospection param that would disable this warning. However, it does not appear that this is ever used so a ticket may need to be filed in graphql-js as well.

Value "literal" must be an enum value

with the latest release i get:

Error: /home/stefano/lavoro/db-network-app/.eslintrc.js: Configuration for rule "graphql/template-strings" is invalid: Value "literal" must be an enum value.
Error: /home/stefano/lavoro/db-network-app/.eslintrc.js:
	Configuration for rule "graphql/template-strings" is invalid:
	Value "literal" must be an enum value.
    at validateRuleOptions (/home/stefano/lavoro/db-network-app/node_modules/eslint/lib/config/config-validator.js:115:15)

looking at source: https://github.com/apollostack/eslint-plugin-graphql/blob/master/src/index.js#L61

it seems that something is missing, or i'm doing something wrong?

my .eslintrc.js is

module.exports = {
  parser: "babel-eslint",
  rules: {
    "graphql/template-strings": ['error', {
      // Import default settings for your GraphQL client. Supported values:
      // 'apollo', 'relay', 'lokka', 'literal'
      env: 'literal',

      // Import your schema JSON here
      schemaJson: require('./app/graphql/schema.json'),

      // OR provide absolute path to your schema JSON
      // schemaJsonFilepath: path.resolve(__dirname, './schema.json'),

      // tagName is gql by default
    }]
  },
  plugins: [
    'graphql'
  ]
}

Suggestion: descriptions for all types

Suggestion:

TypeDescriptions: Always

Checks that types always have descriptions.

bad

type Widget {
  id: ID
  name: String
}

good

# Blocks of content shown on the home page
type Widget {
  id: ID
  name: String
}

How to obtain introspection query result from apollo?

I'm a bit confused by the various ways to define a graphql schema and which is the right one for this plugin. I have a working apollo server instance, where the schema is defined via type definitions:

const resolvers = require('./resolvers');

const typeDefinitions = `
    type Book {
        id: Int!
        name: String!
        authors: [Author]
    }

    type Author {
        id: Int!
        name: String!
    }

    # this schema allows the following two queries:
    type RootQuery {
        book(id: Int): Book
        author(name: String): Author
    }

    # this schema allows the following two mutations:
    type RootMutation {
        createBook(
            name: String!
            author: int!
        ): Book

        createAuthor(
            name: String!
        ): Author
    }

    schema {
        query: RootQuery
        mutation: RootMutation
    }
`;

const executableSchema = makeExecutableSchema({
    typeDefs: [typeDefinitions],
    resolvers
});

export default executableSchema;

But how do I get the introspection query result as mentioned in the README of this repo? I'm a bit confused on what the property schemaJson should look like inside the .eslintrc.js. Are there any examples? The ones I've found so far seem to redeclare the schema definitions specifically for eslint.

Better support for GraphQL literal files

As it stands, it's not very well documented on how to setup parsing of literal files. After some digging through the source, I was able to get the plugin working for literal files by setting tagName to "ESLintPluginGraphQLFile". Could there perhaps be an internal env that would automatically default to this tag name.

Thanks,

Doesn't detect template literal tag in all contexts

Started trying this out today, and it seems like the template literal tag isn't detected in certain context like decorators, meaning incorrect fields aren't flagged by eslint.

Here's a screenshot from the same project, one showing the plugin working with Relay.creatContainer, and the other using a custom relay decorator.

screen shot 2016-04-27 at 11 45 47

Missing Non-Null marked input type not detected

Intended outcome:

Detect that resendUserVerificationInput is supposed to be Non-Null in this query:

#import "fragments/mutationResponseFields.gql"

mutation ResendVerification($input: resendUserVerificationInput) {
  resendUserVerification(input: $input) {
    resendUserVerification {
      user {
        id
        phoneNumber
      }
      ...mutationResponseFields
    }
  }
}

The same query in Graphiql yields this error:
screen shot 2017-03-13 at 08 36 27

Actual outcome:

No error is detected when linting

How to reproduce the issue:

If I introduce a deliberate error e.g. misspell resendUserVerificationInput above errors are properly detected:

/Users/jacob/Code/foo/app/containers/ResendVerification/resendVerification.gql
  4:37  error  Unknown type "resendUserVerificationInputs". Did you mean "resendUserVerificationInput" or "resendUserVerificationPayload"?  graphql/template-strings

My graphql/template-strings configuration:

      "graphql/template-strings": [
        "error",
        {
          "env": "literal",
          "schemaJsonFilepath": "app/schema.json",
          "validators": [
            "ArgumentsOfCorrectType",
            "DefaultValuesOfCorrectType",
            "FieldsOnCorrectType",
            "FragmentsOnCompositeTypes",
            "KnownArgumentNames",
            "KnownTypeNames",
            "LoneAnonymousOperation",
            "NoFragmentCycles",
            "NoUndefinedVariables",
            "NoUnusedVariables",
            "OverlappingFieldsCanBeMerged",
            "PossibleFragmentSpreads",
            "ProvidedNonNullArguments",
            "ScalarLeafs",
            "UniqueArgumentNames",
            "UniqueFragmentNames",
            "UniqueInputFieldNames",
            "UniqueOperationNames",
            "UniqueVariableNames",
            "VariablesAreInputTypes"
          ]
        }
      ]

Excerpt from schema.json for related mutation indicating non null:

{
  "args" : [ {
    "defaultValue" : null,
    "name" : "input",
    "description" : null,
    "type" : {
      "kind" : "NON_NULL",
      "name" : null,
      "ofType" : {
        "kind" : "INPUT_OBJECT",
        "name" : "resendUserVerificationInput",
        "ofType" : null
      }
    }
  } ],
  "deprecationReason" : null,
  "isDeprecated" : false,
  "name" : "resendUserVerification",
  "description" : "resendUserVerification",
  "type" : {
    "kind" : "OBJECT",
    "name" : "resendUserVerificationPayload",
    "ofType" : null
  }
}

Array.prototype.includes is not a function in node versions <= 5

In node V5, the Array.prototype.includes is hidden behind the harmony flag and not supported in earlier versions. In node 5.4.1, using the literal env throws:

TypeError: (0 , _lodash.keys)(...).map(...).includes is not a function

The entry point to the tests have the line:

require('babel-polyfill');

According to the node docs:

This will emulate a full ES2015+ environment and is intended to be used in an application rather than a library/tool.

Using transform-runtime is recommended for library code, which will not include instance methods and built-ins and pollute the global scope.

Per a slack conversation with @stubailo , I will be furnishing a pull request to solve this.

Simplify and improve performance

This plugin is great, but unnecessarily complicated, so I'm suggesting a possibly simpler approach, which also should result in better performance and simplify the code base!

.eslintrc.js:

'graphql/queries': ['error', {
  // Mapping from tag names to config.
  'gql': {
    env: 'apollo',
    projectName: 'apollo',
    validators: [
      'default', // Allows extending the default.
      'NamedOperations', // Replaces `graphql/named-operations`.
      'RequiredFields', // Replaces `graphql/required-fields`.
      'CapitalizedTypeNames', // Replaces `graphql/capitalized-type-name`.
    ],
    requiredFields: ['id'],
  },
  'Relay.QL': {
    env: 'relay',
    projectName: 'relay',
  },
  '.graphql': { // Special name for targeting literal files.
    env: 'apollo', // NOT 'literal'. Want to base `validators` on 'apollo'.
    projectName: 'apollo',
  },
],

.graphqlconfig:

{
  "projects": {
    "apollo": {
      "schemaPath": "./schema-apollo.json"
    },
    "relay": {
      "schemaPath": "./schema-relay.graphql"
    }
  }
}

Changes:

  • graphql/queries, graphql/named-operations, graphql/required-fields and graphql-capitalized-type-name are merged into graphql/template-literals. This means that you won't have to specify the same options to four rules, and that everything can be linted in one pass instead of parsing every GraphQL query four times. All rules already share the same code anyway, and are implemented as validators.

  • graphql/queries takes a single object as config, which is a mapping from tag names that you want to check, to config for that tag name. The special .graphql name maps to .graphql and .gql files (current env: 'literal').

  • env is now required. Explicit is better than implicit.

  • env: 'literal' is removed. As said, '.graphql': {...} is used instead. This also allows specifying env: 'apollo' for .graphql files to get the set of validators for Apollo.

  • schemaJson, schemaJsonFilepath and schemaString are all removed. Just use .graphqlconfig and get it all for free.

  • requiredFields is only required if validators contains 'RequiredFields', and it must contain at least one required field.

What do you think?

Should register props as being used when combined with eslint-react

When writing such code:

class ElectivesView...

const withElectivesData = graphql(ElectivesQuery, {
  options: (ownProps) => ({
    variables: ownProps.electiveVariables
  })
})

export default connect(mapStateToProps, mapDispatchToProps)(withElectivesData(ElectivesView))

I can the following errors:

  • 'electiveVariables' PropType is defined but prop is never used - react/no-unused-prop-types

Generally the plugin works fine, but I think like the JSX plugin registers tags which are used to the imported symbol/variable counter (to find unused variables/imports) we have to do something about the GraphQL methods so that these are correctly regarded their usage of our defined props.

Relay Modern support?

Relay Modern uses an imported graphql tag, so I thought I could get this plugin working with the following config:

{
  tagName: "graphql",
  schemaString: schema,
}

That didn't work, so I tried this as well as I know Relay has a few oddities in the syntax it allows:

{
  env: 'relay',
  tagName: "graphql",
  schemaString: schema,
}

But still nothing. Is Relay Modern supported yet, or am I one config option away? Thanks!

An in-range update of graphql is breaking the build 🚨

Version 0.9.4 of graphql just got published.

Branch Build failing 🚨
Dependency graphql
Current Version 0.9.3
Type dependency

This version is covered by your current version range and after updating it in your project the build failed.

graphql is a direct dependency of this project this is very likely breaking your project right now. If other packages depend on you it’s very likely also breaking them.
I recommend you give this issue a very high priority. I’m sure you can resolve this πŸ’ͺ

Status Details - ❌ **continuous-integration/travis-ci/push** The Travis CI build failed [Details](https://travis-ci.org/apollographql/eslint-plugin-graphql/builds/226667567)

Release Notes v0.9.4

New:

  • All validation rules are now exported directly (#808)

Fixes:

  • Fix flow issue with constructing new GraphQLError() (#829)

Spec Compliance:

  • Now throws error when building Enum with reserved words (#812)
  • Now throws error when building Union with multiple of the same type (#813)
  • Now throws error when building Object type implementing the same Interface more than once (#728)
Commits

The new version differs by 39 commits0.

  • 604bf1a 0.9.4
  • e3c708a Merge pull request #728 from APIs-guru/uniq_interfaces
  • 5e17f83 Merge pull request #813 from APIs-guru/uniq_union
  • b460659 Use hashmap instead of array find
  • 7893dba Use a hashmap instead of array find
  • 13ba225 rm unnecessary change
  • 126cd6d Merge pull request #829 from graphql/graphql-error-constructor
  • 5caf176 Merge pull request #812 from APIs-guru/enumNames
  • a5a9126 Add constructor to GraphQLError class flow type
  • 4abde6e Fix GitHub syntax highlighting (#753)
  • c87fbd7 Freshen yarn.lock
  • 6ceb5a5 Merge pull request #824 from graphql/greenkeeper/mocha-3.3.0
  • 08d6885 Merge pull request #823 from graphql/greenkeeper/flow-bin-0.44.2
  • 10e7b93 chore(package): update mocha to version 3.3.0
  • aea5c45 chore(package): update flow-bin to version 0.44.2

There are 39 commits in total.

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Multiple schemas and tagName

Hi,

From readme:

module.exports = {
  parser: "babel-eslint",
  rules: {
    "graphql/template-strings": ['error', {
      env: 'apollo',
      tagName: 'FirstGQL',
      schemaJson: require('./schema-first.json')
    }, .... ,
  plugins: [
    'graphql'
  ]
}

Where does tagName come from? I thought It was a config in graphql-tag but I found nothing in the repo about it.

From graphql-tag readme:

import gql from 'graphql-tag';
 
const query = gql`
  {
    user(id: 5) {
      firstName
      lastName
    }
  }
`

For me the tagName here is gql and it seeems that it is not possible to change!!!

I have more than one schema and I am using Apollo Client with Angular 4!

Thanks!

"required-fields" rule crash for InlineFragment

Eslint crashes when there's a required field along with an inline fragment.

Eslint config:

"graphql/required-fields": ["error", {
      "requiredFields": ["id"],
      "schemaJsonFilepath": "./data/schema.json"
    }]

Schema:

interface Viewer {
  id: ID!
}
type UserViewer implements Viewer {
  id: ID!
  firstName: String
  lastName: String
}

Query:

{
  viewer {
    ... on UserViewer {
       firstName
    }
  }
}

Intended:

error  'id' field required on 'viewer'

Actual:

Cannot read property 'value' of undefined
TypeError: Cannot read property 'value' of undefined
    at /[...]/node_modules/eslint-plugin-graphql/lib/rules.js:44:26
    at Array.find (native)
    at /[...]/node_modules/eslint-plugin-graphql/lib/rules.js:42:66
[...]

Schema

All documentation on apollo server uses webpack loader and none to generate json file. What is the process o best practice to keep .gql file and the json to get working this lint?

schemaJson field is not well documented or I am missing something?

KnownFragmentNames and NoUnusedFragments across GraphQL file imports

I’m having some issues getting the #import statements to work in my .graphql literal files. Given three files:
src/containers/PolicyReportContainer/policyReportQuery.graphql :

#import "components/StatusPanel/StatusPanelPolicyReport.graphql"
#import "components/PolicyPanel/PolicyPanelPolicyReport.graphql"

query PolicyReport($policyReportId: ID!) {
  carrier_policy_report(id: $policyReportId) {
    ...StatusPanelPolicyReport
    ...PolicyPanelPolicyReport
  }
}

src/components/PolicyPanel/PolicyPanelPolicyReport.graphql :

fragment PolicyPanelPolicyReport on CarrierPolicyReport {
  id
  foo
  bar
}

and src/components/StatusPanel/StatusPanelPolicyReport.graphql :

fragment StatusPanelPolicyReport on CarrierPolicyReport {
  id
  baz
}

I get these errors from the linter:

./src/components/PolicyPanel/PolicyPanelPolicyReport.graphql
  1:0  error  Fragment "PolicyPanelPolicyReport" is never used  graphql/template-strings

./src/components/StatusPanel/StatusPanelPolicyReport.graphql
  1:0  error  Fragment "StatusPanelPolicyReport" is never used  graphql/template-strings

./src/containers/PolicyReportContainer/policyReportQuery.graphql
  11:12  error  Unknown fragment "StatusPanelPolicyReport"  graphql/template-strings

βœ– 3 problems (3 errors, 0 warnings)

looking through the issues on github, I’m not seeing anyone else with this specific problem and others seem to be using the β€˜literal’ option without these kinds of issues. any thoughts? using a simple .eslintrc.js :

module.exports = {
  "parser": "babel-eslint",
  "rules": {
    "graphql/template-strings": [2, {
      env: 'literal',
      schemaJson: require('./schema.json')
    }]
  },
  "plugins": ["graphql"]
}

Per a conversation with @stubailo on Slack, I will submit a PR that removes the KnownFragmentNames and NoUnusedFragments from the default rules in the literal env. Would be interested in contributing a real fix, but will need some guidance.

Support for fragment interpolation in Apollo

Now that we have support for fragment interpolation via graphql-tag (link to relevant deprecation notice in graphql-fragments), we can now do the following in Apollo:

const fragment = gql`
  fragment Foo on SomeResource {
    someField
    ...SomeOtherFragment
  }
  ${SomeOtherFragment}

However, using this syntax gets caught in eslint-plugin-graphql:
image, because previously Apollo recommended against interpolation.

Presumably this is okay to re-enable, but we'd want to still guard against other kinds of interpolation. Perhaps we can allow interpolation if it occurs outside any fragment/query/mutation declarations?

Doesn't work for .graphqlconfig

module.exports = {
  parser: "babel-eslint",
  parserOptions: {
    ecmaVersion: 6,
    sourceType: "module",
    ecmaFeatures: {
      jsx: true,
      modules: true
    }
  },
  env: {
    browser: true,
    node: true,
    mocha: true,
    es6: true
  },
  extends: "airbnb",
  rules: {
    "react/wrap-multilines": "off",
    "react/require-extension": "off",
    'graphql/template-strings': ['error', {
      env: 'relay',
      tagName: 'graphql',
    }],
  },
  overrides: [
    {
      files: [
        "**/actions.js"
      ],
      rules: {
        "import/prefer-default-export": "off"
      }
    }
  ],
  plugins: [
    "react",
    "graphql",
  ]
}
{
  "schemaPath": "schema.graphql",
  "extensions": {
    "endpoints": {
      "dev": "http://localhost:8080/graphql"
    }
  }
}

Error:

Schema must be an instance of GraphQLSchema. Also ensure that there are not multiple versions of GraphQL installed in your node_modules directory.

If I remove tagName I get no error but linting does not work still.

If I specify a path to a json schema it works fine but according to the docs I shouldn't have to do this. Both files are in my root.

Unknown directive "relay"

I get this error when using Relay directives in my queries. I think this is because Relay's directives are purely client-side, so aren't included in the schema.

Example query:

fragment on CreateEventPayload @relay(pattern: true) {
  viewer {
    events
  }
  user {
    events
  }
}

Invalid "Variable is never used" warning

First off, great tool! I haven't dug too far into it, but I just loaded it up with this gql query / fragment combo and I'm seeing the error:

Variable $first is never used in operation "getUserTracks".

If i'm not mistaken, it's not taking into account any fragments which might eventually make use of the variable (which seems to be allowed in the spec)?

const myItemsFragment = createFragment(gql`
  fragment myItems on AuthenticatedUser {
    tracks(first: $first, after: $offset) {
      edges {
        cursor
        item: node {
          ...itemFragment
        }
      }
      pageInfo {
        endCursor
      }
    }
  }
`)

const ConnectedRows = graphql(gql`
  query getUserItems($first: Int!, $offset: String) {
    me {
      displayName,
      ...myItems
    }
  }
`, {
  options: {
    fragments: [myItemsFragment, itemFragment],
  },
  props({data: { loading, me }}) {
    if (loading) {
      return {
        loading
      }
    }
    const { items, ...userInfo } = me
    return {
      loading,
      userInfo,
      items: me.items.edges,
      after: me.items.pageInfo.endCursor
    }
  }
})(Rows);

required-fields rule causes ESLint crash when referencing non-existent field

When running eslint against code that has a bad field reference (nx does not exist):

// ...

const query = gql`
query Blah {
  thing {
    foo
    bar
    nx
  }
}
`;

Intended outcome: "field nx does not exist"

Actual outcome:

Cannot read property 'type' of undefined
TypeError: Cannot read property 'type' of undefined
    at .../node_modules/eslint-plugin-graphql/lib/rules.js:28:39
    at Array.forEach (native)
    at Object.Field (.../node_modules/eslint-plugin-graphql/lib/rules.js:27:22)
    at Object.enter (.../node_modules/graphql/language/visitor.js:297:29)
    at Object.enter (.../node_modules/graphql/language/visitor.js:339:25)
    at visit (.../node_modules/graphql/language/visitor.js:229:26)
    at visitUsingRules (.../node_modules/graphql/validation/validate.js:77:22)
    at validate (.../node_modules/graphql/validation/validate.js:62:10)
    at handleTemplateTag (.../node_modules/eslint-plugin-graphql/lib/index.js:353:57)
    at EventEmitter.TaggedTemplateExpression (.../node_modules/eslint-plugin-graphql/lib/index.js:112:20)

I believe something like this should fix it: benjie@0d6214d

(In fact I just went in and edited the file in node_modules and that does indeed fix the issue.)

ESLint rules snippet:

    "graphql/template-strings": [
      "error",
      {
        env: "apollo",
        schemaJson: require("./data/schema.json"),
      },
    ],
    "graphql/required-fields": [
      "error",
      {
        schemaJson: require("./data/schema.json"),
        requiredFields: ["__typename", "id"],
      },
    ],

Add Required Fields rule support for literal env

Current behavior:

required-fields rule only allows a tagName option in the configuration, so does not work with the literal env

Desired behavior:

Add an optional env property to the rule to allow .graphql files to be linted with this rule.

Trouble with .graphqlconfig / bad config validation / questions

Sorry for bundling several things into one issue. I initally had just one problem, but when diagnosing it things snowballed.

TL;DR: This plugin works super well, just need to look over config validation in general .)

Here's the test repo: https://github.com/lydell/eslint-plugin-graphql-bug

graphql/named-operations .graphqlconfig problem

I tried switching from schemaJson: require("./schema.json") to using .graphqlconfig. This worked well for the graphql/template-strings rule, but I got trouble with the graphql/named-operations rule.

Using .graphqlconfig it looks as if no additional config is need for the graphql/named-operations rule in .eslintrc.js. So I tried this:

"graphql/named-operations": "error",

But then nothing is reported. This works, though:

"graphql/named-operations": ["error", {}],

graphql/capitalized-type-name .graphqlconfig problem

Same thing here. It looks as if this should be enough:

"graphql/capitalized-type-name": "error",

This results in a validation error:

"graphql/capitalized-type-name": ["error", {}],
Configuration for rule "graphql/capitalized-type-name" is invalid:
  Value "[object Object]" should have required property '.schemaJson'.
  Value "[object Object]" should have required property '.schemaJsonFilepath'.
  Value "[object Object]" should have required property '.schemaString'.
  Value "[object Object]" should match exactly one schema in oneOf.

I couldn't get this rule to work .graphqlconfig.

Questions

Diagnosing the above problems and looking at the other rules, I stumbled upon some questions:

  • Why does graphql/named-operations require a schema?
  • Why does graphql/capitalized-type-name require a schema?
  • Why does graphql/required-fields let you specify env?
    • It seems to be optional, so what's the default?
  • Is env required for graphql/template-strings? It does not seem so when I
    tested. What's the default?

Other minor config validation quirks

They're all described in https://github.com/lydell/eslint-plugin-graphql-bug

Support .eslintrc.json?

Is JSON format for ESlint config supported? It looks like schemaJson doesn't support file paths.

An in-range update of babel-eslint is breaking the build 🚨

Version 7.2.3 of babel-eslint just got published.

Branch Build failing 🚨
Dependency babel-eslint
Current Version 7.2.2
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As babel-eslint is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ

Status Details - ❌ **continuous-integration/travis-ci/push** The Travis CI build failed [Details](https://travis-ci.org/apollographql/eslint-plugin-graphql/builds/224535482)

Commits

The new version differs by 2 commits0.

false

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

An in-range update of mocha is breaking the build 🚨

Version 3.3.0 of mocha just got published.

Branch Build failing 🚨
Dependency mocha
Current Version 3.2.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As mocha is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ

Status Details - ❌ **continuous-integration/travis-ci/push** The Travis CI build failed [Details](https://travis-ci.org/apollographql/eslint-plugin-graphql/builds/225175621)

Release Notes coverave

Thanks to all our contributors, maintainers, sponsors, and users! ❀️

As highlights:

  • We've got coverage now!
  • Testing is looking less flaky \o/.
  • No more nitpicking about "mocha.js" build on PRs.

πŸŽ‰ Enhancements

  • #2659: Adds support for loading reporter from an absolute or relative path (@sul4bh)
  • #2769: Support --inspect-brk on command-line (@igwejk)

πŸ› Fixes

  • #2662: Replace unicode chars w/ hex codes in HTML reporter (@rotemdan)

πŸ” Coverage

πŸ”© Other

Commits

The new version differs by 89 commits0.

  • fb1687e :ship: Release v3.3.0
  • 1943e02 Add Changelog for v3.3.0
  • 861e968 Refactor literal play-icon hex code to a var
  • 1d3c5bc Fix typo in karma.conf.js
  • 9bd9389 Fix spec paths in test HTML files
  • 0a93024 Adds tests for loading reporters w/ relative/absolute paths (#2773)
  • 73929ad Comment special treatment of '+' in URL query parsing
  • e2c9514 Merge pull request #2769 from igwejk/support_inspect_break_in_opts
  • 038c636 Support --inspect-brk on command-line
  • b4ebabd Merge pull request #2727 from lamby/reproducible-build
  • 882347b Please make the build reproducible.
  • a2fc76c Merge pull request #2703 from seppevs/cover_utils_some_fn_with_tests
  • ed61cd0 cover .some() function in utils.js with tests
  • f42cbf4 Merge pull request #2701 from craigtaub/landingSpec
  • 6065242 use stubbed symbol

There are 89 commits in total.

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Update graphql peer dependency

graphql@^0.11.0 needs to be supported.

I suspect this is causing this error when attempting to lint:

Schema must be an instance of GraphQLSchema. Also ensure that there are not multiple versions of GraphQL installed in your node_modules directory.

Some issues with Relay Modern

So after I got this running against a Relay Modern project, I've noticed some issues with Relay Modern:

  • Relay Modern's createPaginationContainer requires the use of a connection directive, e.g: things(first: 10) @connection(key: "ThingsList_things") { name }. This flags up a linting error Unknown directive 'connection'.
  • Relay Modern uses named fragments that follow a ComponentName_PropName format, and then uses its relay-compiler to build queries across different files using those names. For example, in ThingViewer.js you'd have a fragment like fragment ThingViewer_thing on Thing { name, colour } ThingList.js you'd have a query like fragment ThingList_things on ThingCollection { numberOfThings, things { ...ThingViewer_thing } }. Because these fragments are defined in different queries across different files, the linting error Unknown fragment "ThingViewer_thing" and Fragment "ThingViewer_thing" is never used.

Suggestion: type name capitalization

Suggestion:

TypeNameCap: true

Check that the first letter of types is always capitalized.

# bad
type link {
  href: String
  title: String
}
# good
type Link {
  href: String
  title: String
}

Add support for linting optional GraphQL rules

Currently, eslint-plugin-graphql will check gql tagged templates against a provided schema. However, there are a certain set of "optional" GraphQL parameters that aren't a part of the schema but would be handy rules to lint against anyway.

For example, specifying the operationName is a very useful tool for "tagging" your GraphQL queries (see @stubailo's explanation here). Having a lint rule that allowed you to optionally enforce a unique operation name would help make this more widespread (should you choose to enable it).

Additionally, depending on which GraphQL client you use, naming your fragments may be a necessary part of the developer workflow - having the eslint-plugin-graphql lint to make sure you're naming your fragments would be useful.

In both cases, it might even be nice to establish a format for that name, given the module or component name (in React).

Is this a problem you've faced while using GraphQL?

Support for GraphQL IDL schema file

Feature suggestion: the linter, unlike graphql-tool’s makeExecutableSchema, relies not on a GraphQL IDL file, but instead on the much longer introspection query file.

I version control my schema with each client, so there test suites can be run against a static target, it would be nice (tm) if I didn't need to do any legwork to convert my IDL to the JSON format.

Add error for duplicate keys

This may sound kind of dumb, but it would still be nice to have. If I put the same key twice inside of a query, could we make it display an error message? If so, I’d be interested in making a PR

False positive thrown on variable used in RelayQueryConfig

export class NodeQueryConfig extends Relay.Route {
  static paramDefinitions = {
    nodeID: { required: true },
  };
  static routeName = 'NodeConfig';
  static queries = {
    node: () => Relay.QL`
      query {
        node(id: $nodeID)
      }
    `,
  };
}

Returns the error Variable "$nodeID" is not defined. Looks like the paramDefinitions property isn't being picked up.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.