Skip to content

Commit

Permalink
Add options to input-name rule. Addresses #276 (#286)
Browse files Browse the repository at this point in the history
* Add caseSensitiveInputType, checkMutations, checkQueries options to input-name rule

caseSensitiveInputType: When false the input type name must be <mutationName>Input but is not case sensitive.

checkMutations (default true): Apply this rule to mutations.

checkQueries (default false): Apply this rule to queries.

Also fixed documentation error which says that checkInputType defaults to true, when infact it defaults to false.

* added changeset

Co-authored-by: Dotan Simha <dotansimha@gmail.com>
  • Loading branch information
lioneltay and dotansimha committed Feb 2, 2021
1 parent 619d9eb commit 5b35139
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/early-turkeys-admire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-eslint/eslint-plugin': minor
---

Add options to input-name rule.
65 changes: 53 additions & 12 deletions packages/plugin/src/rules/input-name.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { GraphQLESLintRule } from '../types';

type InputNameRuleConfig = [
{
checkInputType?: boolean;
}
];
type InputNameRuleConfig = {
checkInputType?: boolean;
caseSensitiveInputType?: boolean;
checkQueries?: boolean;
checkMutations?: boolean;
};

const rule: GraphQLESLintRule<InputNameRuleConfig> = {
const rule: GraphQLESLintRule<InputNameRuleConfig[]> = {
meta: {
type: 'suggestion',
docs: {
Expand Down Expand Up @@ -52,31 +53,65 @@ const rule: GraphQLESLintRule<InputNameRuleConfig> = {
properties: {
checkInputType: {
type: 'boolean',
default: 'true',
default: false,
description: 'Check that the input type name follows the convention <mutationName>Input',
},
caseSensitiveInputType: {
type: 'boolean',
default: true,
description: 'Allow for case discrepancies in the input type name',
},
checkQueries: {
type: 'boolean',
default: false,
description: 'Apply the rule to Queries',
},
checkMutations: {
type: 'boolean',
default: true,
description: 'Apply the rule to Mutations',
},
},
additionalProperties: false,
},
],
},
create(context) {
const options: InputNameRuleConfig = {
caseSensitiveInputType: true,
checkInputType: false,
checkMutations: true,
checkQueries: false,
...context?.options?.[0],
};

const isMutationType = node => {
return (
(node.type === 'ObjectTypeDefinition' || node.type === 'ObjectTypeExtension') && node.name.value === 'Mutation'
);
};

const isQueryType = node => {
return (
(node.type === 'ObjectTypeDefinition' || node.type === 'ObjectTypeExtension') && node.name.value === 'Query'
);
};

const shouldCheckType = node =>
(options.checkMutations && isMutationType(node)) || (options.checkQueries && isQueryType(node));

const listeners = {
'FieldDefinition > InputValueDefinition': node => {
if (node.name.value !== 'input' && isMutationType(node.parent.parent)) {
if (node.name.value !== 'input' && shouldCheckType(node.parent.parent)) {
context.report({
node: node.name,
message: `Input "${node.name.value}" should be called "input"`,
});
}
},
};
if (context.options && context.options[0] && context.options[0].checkInputType) {

if (options?.checkInputType) {
listeners['FieldDefinition > InputValueDefinition NamedType'] = node => {
const findInputType = item => {
let currentNode = item;
Expand All @@ -87,11 +122,17 @@ const rule: GraphQLESLintRule<InputNameRuleConfig> = {
};

const inputValueNode = findInputType(node);
if (isMutationType(inputValueNode.parent.parent)) {
if (shouldCheckType(inputValueNode.parent.parent)) {
const mutationName = `${inputValueNode.parent.name.value}Input`;

if (node.name.value !== mutationName) {
context.report({ node, message: `InputType "${node.name.value}" name should be "${mutationName}"` });
if (options.caseSensitiveInputType) {
if (node.name.value !== mutationName) {
context.report({ node, message: `InputType "${node.name.value}" name should be "${mutationName}"` });
}
} else {
if (node.name.value.toLowerCase() !== mutationName.toLowerCase()) {
context.report({ node, message: `InputType "${node.name.value}" name should be "${mutationName}"` });
}
}
}
};
Expand Down
44 changes: 44 additions & 0 deletions packages/plugin/tests/input-name.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ const ruleTester = new GraphQLRuleTester();

ruleTester.runGraphQLTests('input-name', rule, {
valid: [
{
code: 'type Mutation { SetMessage(input: SetMessageInput): String }',
options: [{ checkInputType: true }],
},
{
code: 'type Mutation { SetMessage(input: SetMessageInput): String }',
options: [{ checkInputType: true }],
Expand All @@ -25,6 +29,31 @@ ruleTester.runGraphQLTests('input-name', rule, {
'type Mutation { CreateMessage(input: String): String }',
'extend type Mutation { CreateMessage(input: String): String }',
'type Query { message(id: ID): Message }',
'extend type Query { message(id: ID): Message }',
{
code: 'type Mutation { userCreate(input: UserCreateInput): String }',
options: [{ checkInputType: true, caseSensitiveInputType: false }],
},
{
code: 'type Mutation { userCreate(input: userCreateInput): String }',
options: [{ checkInputType: true, caseSensitiveInputType: true }],
},
{
code: 'type Mutation { SetMessage(input: NonConforming): String }',
options: [{ checkMutations: false, checkInputType: true }],
},
{
code: 'type Mutation { SetMessage(input: String): String }',
options: [{ checkMutations: true, checkInputType: false }],
},
{
code: 'type Query { getMessage(input: NonConforming): String }',
options: [{ checkQueries: false, checkInputType: true }],
},
{
code: 'type Query { getMessage(input: String): String }',
options: [{ checkQueries: true, checkInputType: false }],
},
],
invalid: [
{
Expand Down Expand Up @@ -75,5 +104,20 @@ ruleTester.runGraphQLTests('input-name', rule, {
options: [{ checkInputType: false }],
errors: 2,
},
{
code: 'type Mutation { userCreate(input: String): String }',
options: [{ checkInputType: true, caseSensitiveInputType: false }],
errors: 1,
},
{
code: 'type Mutation { userCreate(input: UserCreateInput): String }',
options: [{ checkInputType: true, caseSensitiveInputType: true }],
errors: 1,
},
{
code: 'type Query { getUser(input: GetUserInput): String }',
options: [{ checkQueries: true, checkInputType: true, caseSensitiveInputType: true }],
errors: 1,
},
],
});

0 comments on commit 5b35139

Please sign in to comment.