Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

eslint-plugin-graphql

apollostack1mMIT4.0.0

GraphQL ESLint plugin.

readme

eslint-plugin-graphql

npm version Build Status Get on Slack

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'
  ]
}

changelog

Change log

vNEXT

  • Nothing yet!

v4.0.0

v3.1.1

  • Update the required-fields rule to handle inline fragments without field ancestors. PR #240 by Henry Q. Dineen

v3.1.0

  • Fix an issue that caused graphql/required-fields to throw on non-existent field references. PR #231 by Vitor Balocco
  • chore: Update dependency graphql-tools to v4.0.5. PR #239
  • chore: Update dependency eslint to v5.16.0. PR #218
  • chore: Update dependency graphql to v14.4.2. PR #220
  • chore: Update dependency test-all-versions to v4.1.1. PR #230
  • chore: Update dependency lodash to v4.17.13. PR #234
  • chore: Update dependency mocha to v6. PR #213
  • chore: Running prettier on all files PR #237

v3.0.3

  • chore: Update dependency graphql-tools to v4.0.4. PR #210
  • chore: Update dependency eslint to v5.12.1. PR #206
  • chore: Update dependency graphql to v14.1.1. PR #208

v3.0.2

  • Fix regression which caused graphql/required-fields to throw on non-existent field references. PR #203 by Matt Bretl

v3.0.1

v3.0.0

  • BREAKING: The required-fields rule has been significantly changed to make it a completely reliable method of ensuring an id field (or any other field name) is always requested when available. PR #199 Here is the behavior, let's say we are requiring field id:
    • On any field whose return type defines a field called id, the selection set must directly contain id.
    • In any named fragment declaration whose type defines a field called id, the selection set must directly contain id.
    • An inline fragment whose type defines a field called id must contain id in its selection set unless its parent is also an inline fragment that contains the field id.
    • Here's a specific case which is no longer valid:
      • query { greetings { hello ... on Greetings { id } } }
      • This must now be written as query { greetings { id hello ... on Greetings { id } } }
    • This is a more conservative approach than before, driven by the fact that it's quite hard to ensure that a combination of inline fragments actually covers all of the possible types of a selection set.
  • Fix breaking change in graphql@^14.0.0 that renamed ProvidedNonNullArguments to ProvidedRequiredArguments #192
  • Update dependencies to graphql-tools 4 and eslint 5.9 #193

v2.1.1

  • Fix support for InlineFragments with the required-fields rule in #140 by Steve Hollaar
  • Fix error location information for literal .graphql files and strings with leading newlines in #122 by Dan Freeman
  • Add fraql environment

v2.1.0

  • Retrieves .graphqlconfig relative to the file being linted, which re-enables support for vscode-eslint using .graphqlconfig in #108 by [Jon Wong][https://github.com/jnwng/]
  • Cache schema reading/parsing results each time a rule is created in #137 by Kristján Oddsson

v2.0.0

v1.5.0

v1.4.1

Skipped v1.4.0 because of incorrect version tag in package.json

v1.3.0

v1.2.0

v1.1.0

v1.0.0

v0.8.2

  • Remove KnownFragmentNames and UnusedFragment from default rules in literal env. Justin Schulz in #70

v0.8.1

  • Fix graphql/required-fields throwing on non-existent field reference Benjie in #65

v0.8.0

  • Updated graphql dependency to resolve test failures (wording change, no API change) jnwng
  • Add lint rule to enforce that required fields are specified. rgoldfinger in #47

v0.7.0

  • Add lint rule to enforce that operations have names gauravmk in #47

v0.6.1

  • Remove babel-polyfill from runtime dependencies, since it was only being used in test code. joelgriffith in #44

v0.6.0

v0.5.0

  • Take into account Apollo fragment interpolation rules jnwng in #33
  • Update graphql-js dependency to 0.8.2 jonbretman in #40

v0.4.3

  • Add 'literal' option to options schema, so that it can actually be used. stefanorg in #39

v0.4.2

  • Added 'literal' option to env for when working with .graphql and .gql files, by jtmthf in #36

v0.4.1

v0.4.0

v0.3.1

  • We didn't keep track of changes before this version. Consult the commit log.