Skip to content

Conversation

@dotansimha
Copy link
Member

@dotansimha dotansimha commented May 26, 2021

Inspiration: https://twitter.com/nodkz/status/1397418250057797632

I think we have many options here, so I'm not sure how to address the comparison:

  • Ignore case
  • compare by sections (userById can match a file name user-by-id.graphql)
  • Suffix support (Fragment User can be in a file called user.fragment.graphql)
  • More use case? 🤔

@changeset-bot
Copy link

changeset-bot bot commented May 26, 2021

🦋 Changeset detected

Latest commit: 04dfab3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@graphql-eslint/eslint-plugin Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@theguild-bot
Copy link
Collaborator

theguild-bot commented May 26, 2021

The latest changes of this PR are available as alpha in npm (based on the declared changesets):

@graphql-eslint/[email protected]

@dotansimha dotansimha marked this pull request as draft May 26, 2021 05:37
@dotansimha dotansimha changed the title 🎉 NEW PLUGIN: Compare operation/fragment name to the file name 🎉 NEW RULE: Compare operation/fragment name to the file name May 26, 2021
@nodkz
Copy link

nodkz commented May 26, 2021

@dotansimha thanks a lot, as always incredible feedback/support from The Guild! 🙏👍🔥

So let's start forming requirements.

What we have now

In our client apps, we have the following .graphql files:

1) UsersPaginationQuery.graphql

query UsersPaginationQuery {
  userPagination {
    count
    items {
      ...UserDataFragment
    }
  }
}

2) UserUpdateMutation.graphql

mutation UserUpdateMutation($input: UserCreateInput!) {
  user {
    update(input: $input) {
      recorded
      record {
         ...UserDataFragment
      }
    }
  }
}

3) UserUpdateSubscription.graphql

subscription UserUpdateSubscription($id: ID!) {
  userUpdate(id: $id) {
      ...UserDataFragment
    }
  }
}

4) UserDataFragment.graphql

fragment UserDataFragment on User {
  id
  nickname
  avatar
}

We are using exact naming for operations/fragments and files. It helps understand what exactly inside. Also according to this requirement, we have suffixes Query/Mutation/Subscription/Fragment to distinguish what exactly inside. And when we are working with React components and Typescript we understood what type/interface we are using – from graphql or some internal client type.

Our current problems:

  • sometimes we rename operation but forget to rename the file
  • sometimes newcomers may not add suffixes
  • some old parts of our apps don't use Fragment suffix

Desirable options

  • filenameStyle: oneOf(['CamelCase.graphql', 'CamelCaseOperation.graphql', 'CamelCase.Operation.graphql', 'camelCase.graphql', 'camelCaseOperation.graphql', 'camelCase.operation.graphql', 'kebab-case.graphql', 'kebab-case-operation.graphql'] - we should support different naming styles but they should be strict.
    • if the operation name does not have suffix (Query,Mutation,...) we can take it from the operation keyword
    • we should not have duplicate sufixies like 'UserUpdateSubscription.Subscription.graphql'
    • it will be nice to have a pattern for filenames '%{operation}__%{style}.gql' -> subscription__userUpdate.gql where exist the following placeholders ['CamelCase', 'camelCase', 'kebab-case', 'operation', 'Operation'] and developers may create any crazy pattern for theirs filenames
    • by default, I recommend using CamelCaseOperation.graphql for keeping in sync all three worlds (graphql, filesystem, typescript)
  • useSuffixes: manyOf(['Query', 'Mutation', 'Subscription', 'Fragment']) - you may exclude any suffix from filenames eg. for fragments.
    • by default: ['Query', 'Mutation', 'Subscription', 'Fragment'].

Desirable options (v2) most configurable format

By the way, it will be nice if we can somehow provide the ability to set different patterns for different operations. In such case config can have the following form:

{
 query: '%{CamelCase}Query.graphql',
 mutation: '%{CamelCase}Mutation.graphql', 
 subscription: '%{CamelCase}Subscription.graphql', 
 fragment: '%{camelCase}.graphql', // by default should be '%{CamelCase}Fragment.graphql', 
}

Instead of masks %{}, we can use more powerful regexps which provide the ability to use OR, Neglect and any crazy pattern logic:

{
 query: '[A-Z]{1}[a-zA-Z0-9_]*Query\.(graphql|gql)', // by default should be '[A-Z]{1}[a-zA-Z0-9_]*Query\.graphql', 
 mutation: '[A-Z]{1}[a-zA-Z0-9_]*Mutation\.graphql',
 subscription: '[A-Z]{1}[a-zA-Z0-9_]*Subscription\.graphql',
 fragment: '[A-Z]{1}[a-zA-Z0-9_]*\.graphql', // by default should be '[A-Z]{1}[a-zA-Z0-9_]*Fragment\.graphql', 
}

Such config a little bit verbose, but helps precisely control filenames.

@nodkz
Copy link

nodkz commented May 26, 2021

Another plugin

PS. This rule should control only filenames. But what about the similar new rule which will control operation names? Eg with the following config:

{
 query: '[A-Z]{1}[a-zA-Z0-9_]*Query',
 mutation: '[A-Z]{1}[a-zA-Z0-9_]*Mutation', 
 subscription: '[A-Z]{1}[a-zA-Z0-9_]*Subscription', 
 fragment: '[A-Z]{1}[a-zA-Z0-9_]_[a-zA-Z0-9_]+', // Relay pattern `TypeName_prop` by default should be '[A-Z]{1}[a-zA-Z0-9_]*Fragment', 
 noDoubleSuffixes: true,  // avoid QueryQuery, MutationQuery
}

@dotansimha dotansimha marked this pull request as ready for review September 6, 2021 09:09
added changeset

make works `match-document-filename` rule (#591)
@dotansimha
Copy link
Member Author

@B2o5T made this a reality :) It's going to be part of the next release!

@dotansimha dotansimha merged commit c6886ba into master Sep 6, 2021
@dotansimha dotansimha deleted the file-name-compare branch September 6, 2021 09:15
@dotansimha
Copy link
Member Author

Available in @graphql-eslint/[email protected]. Thanks @B2o5T @nodkz !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

4 participants