GraphQL-ESLint v3.14 - What's New?

Dimitri POSTOLOV

Introduction

Hi! I am Dimitri 👋, the current maintainer of the GraphQL-ESLint linter, and today I want to share with you all changes that were made in the last version. This is a small minor version update, but a bunch of new rules and options were added.

💡

If you are not familiar with GraphQL-ESLint check out here an introduction blog post by GraphQL-ESLint creator Dotan Simha.

Support New ESLint Flat Config System

Say Hello to the new flat config system!

GraphQL-ESLint v3.14 fully supports the new ESLint flat config system, most of the examples were updated to show you how you will set it up in the newly eslint.config.js file in the following years!

ESLint Suggestions for graphql-js Rules

All graphql-js rules that contain “Did you mean” suggestions now can be fixable via ESLint suggestions API in your editor 🎉.

GraphQL-JS suggestions in VSCode

Update of graphql-config

GraphQL-ESLint comes with a new GraphQL Config v4.4 that no longer requires a typescript dependency to be installed.

💡

Also, GraphQL Config is no longer bundled with cosmiconfig-toml-loader and cosmiconfig-typescript-loader. You must install it manually in case of using TOML or TypeScript config. The benefit of this is that bundle size is reduced by 35%.

New Rules

The new version introduces 4 new rules:

Rule require-nullable-fields-with-oneof

Require input or type fields to be non-nullable with @oneOf directive

.eslintrc.json
{
  "rules": {
    "@graphql-eslint/require-nullable-fields-with-oneof": "error"
  }
}
❌ Incorrect
input Input @oneOf {
  foo: String!
  bar: [Int!]!
}
✅ Correct
input Input @oneOf {
  foo: String
  bar: [Int!]
}

Rule require-type-pattern-with-oneof

Enforce types with @oneOf directive have error and ok fields.

  • It’s easier to communicate user errors in the response
  • Errors can contain any additional info the client might need (error code, validation info and so on)
  • Reduce the need to use ... on Error and so on, no need to specify type names in the query
.eslintrc.json
{
  "rules": {
    "@graphql-eslint/require-type-pattern-with-oneof": "error"
  }
}
❌ Incorrect
type DoSomethingMutationResult @oneOf {
  notok: DoSomethingSuccess
  noterror: Error
}
✅ Correct
type DoSomethingMutationResult @oneOf {
  ok: DoSomethingSuccess
  error: Error
}

Rule lone-executable-definition

Require queries, mutations, subscriptions or fragments to be located in separate files.

.eslintrc.json
{
  "rules": {
    "@graphql-eslint/lone-executable-definition": "error"
  }
}
❌ Incorrect
# users.graphql
query Users {
  users {
    ...UserFields
  }
}
fragment UserFields on User {
  id
}
✅ Correct
# users.graphql
query Users {
  users {
    ...UserFields
  }
}

Rule no-one-place-fragments

An original proposal for a rule to suggest inline fragments that are spread only in one place was asked 2 years ago and finally, this rule is a part of GraphQL-ESLint.

.eslintrc.json
{
  "rules": {
    "@graphql-eslint/no-one-place-fragments": "error"
  }
}
❌ Incorrect
fragment UserFields on User {
  id
}
 
{
  user {
    ...UserFields
  }
}
✅ Correct
{
  user {
    ...UserFields
    friends {
      ...UserFields
    }
  }
}

New Options

groups Option for alphabetize Rule

alphabetize rule is one of the powerful GraphQL-ESLint rules, that can sort all the things in your GraphQL, it also supports ESLint suggestions fixes.

Unfortunately, before it was not possible to configure to put some properties at the start or at the end, but now it was fixed with new option groups.

Here is an example of configuration and cases:

.eslintrc.json
{
  "rules": {
    "@graphql-eslint/alphabetize": [
      "error",
      {
        "fields": ["ObjectTypeDefinition"],
        "groups": ["id", "*", "createdAt", "updatedAt"]
      }
    ]
  }
}
⚠️
* symbol is mandatory, which means everything else.
❌ Incorrect
type User {
  createdAt: DateTime!
  email: Email!
  firstName: String!
  id: ID!
  lastName: String!
  updatedAt: DateTime!
}
✅ Correct
type User {
  id: ID!
  email: Email!
  firstName: String!
  lastName: String!
  createdAt: DateTime!
  updatedAt: DateTime!
}

rootField Option for require-description Rule

This option enforces each field of root type (Query, Mutation and Subscription) to have a description.

.eslintrc.json
{
  "rules": {
    "@graphql-eslint/require-description": ["error", { "rootField": true }]
  }
}
❌ Incorrect
type Mutation {
  createUser: User
}
 
type User {
  name: String
}
✅ Correct
type Mutation {
  "Create a new user"
  createUser: User
}
 
type User {
  name: String
}

prefix Option for match-document-filename Rule

Previously in this rule, we had only a suffix option but in our open-source SAAS project Hive, we prefix all files with executable definitions with their operation types.

Now, everybody can take benefit from this new option 🎉.

.eslintrc.json
{
  "rules": {
    "@graphql-eslint/match-document-filename": [
      "error",
      {
        "mutation": {
          "style": "kebab-case",
          "prefix": "mutation."
        }
      }
    ]
  }
}
❌ Incorrect
# createUser.graphql
 
mutation CreateUser {
  # ...
}
✅ Correct
# mutation.create-user.graphql
 
mutation CreateUser {
  # ...
}

Next Steps

Check out the roadmap for the V4 version, the next major will be released once ESLint 9 will out and of course, propose your suggestions 🙂.

Don’t forget to give a star ⭐️ for GraphQL-ESLint if you like it!

And Happy New 2023 Year! 🎄🎉 🥂

Community

Thanks to our contributors @FloEdelmann, @TuvalSimha and @tshedor.

Join our newsletter

Want to hear from us when there's something new?
Sign up and stay up to date!

*By subscribing, you agree with Beehiiv’s Terms of Service and Privacy Policy.