From 4a3244c854b1fdf4621c515fc8ea5cd941dd504a Mon Sep 17 00:00:00 2001 From: Solomon English Date: Fri, 12 Jun 2020 10:44:01 -0700 Subject: [PATCH 1/2] add a rule to capitalize named operations --- README.md | 42 +++++++++++++++++++ src/customGraphQLValidationRules.js | 12 ++++++ src/index.js | 23 ++++++++++ .../capitalized-named-operations.js | 41 ++++++++++++++++++ test/validationRules/index.js | 1 + 5 files changed, 119 insertions(+) create mode 100644 test/validationRules/capitalized-named-operations.js diff --git a/README.md b/README.md index a85a642..f4c417c 100644 --- a/README.md +++ b/README.md @@ -399,6 +399,48 @@ module.exports = { ] } ``` + +### Capitalization of a first letter of Named Operation rule + +**Pass** +``` +query FetchUsername { + viewer { + name + } +} +``` + +**Fail** +``` +query fetchUsername { + viewer { + name + } +} +``` + +The rule is defined as `graphql/capitalized-named-operations`. + +```js +// In a file called .eslintrc.js +module.exports = { + parser: "babel-eslint", + rules: { + "graphql/template-strings": ['error', { + env: 'apollo', + schemaJson: require('./schema.json'), + }], + "graphql/capitalized-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. diff --git a/src/customGraphQLValidationRules.js b/src/customGraphQLValidationRules.js index 0600bba..e9c8402 100644 --- a/src/customGraphQLValidationRules.js +++ b/src/customGraphQLValidationRules.js @@ -1,5 +1,17 @@ import { GraphQLError, getNamedType } from "graphql"; +export function OperationNamesMustBeCapitalized(context) { + return { + OperationDefinition(node) { + if (node.name && node.name.value && (node.name.value[0] == node.name.value[0].toLowerCase())) { + context.reportError( + new GraphQLError("All operations must be capitalized", [node]) + ); + } + } + }; +} + export function OperationsMustHaveNames(context) { return { OperationDefinition(node) { diff --git a/src/index.js b/src/index.js index 144db0b..08af35f 100644 --- a/src/index.js +++ b/src/index.js @@ -178,6 +178,29 @@ export const rules = { ); } }, + "capitalized-named-operations": { + meta: { + schema: { + type: "array", + items: { + additionalProperties: false, + properties: { ...defaultRuleProperties }, + ...schemaPropsExclusiveness + } + } + }, + create: context => { + return createRule(context, optionGroup => + parseOptions( + { + validators: ["OperationNamesMustBeCapitalized"], + ...optionGroup + }, + context + ) + ); + } + }, "required-fields": { meta: { schema: { diff --git a/test/validationRules/capitalized-named-operations.js b/test/validationRules/capitalized-named-operations.js new file mode 100644 index 0000000..b8e86e5 --- /dev/null +++ b/test/validationRules/capitalized-named-operations.js @@ -0,0 +1,41 @@ +import { rules } from "../../src"; +import schemaJson from "../schema.json"; + +import { ruleTester, parserOptions } from "../helpers"; + +const capitalizedNamedOperationsValidatorCases = { + pass: [ + "const x = gql`query Test { sum(a: 1, b: 2) }`", + "const x = gql`query { sum(a: 1, b: 2) }`", + ], + fail: [{ + code: "const x = gql`query test { sum(a: 1, b: 2) }`", + errors: [ + { + message: "All operations must be capitalized", + type: "TaggedTemplateExpression" + } + ] + }] +}; + +// Validate the named-operations rule +const options = [ + { + schemaJson, + tagName: "gql" + } +]; +ruleTester.run("testing capitalized-named-operations rule", rules["capitalized-named-operations"], { + valid: capitalizedNamedOperationsValidatorCases.pass.map(code => ({ + options, + parserOptions, + code + })), + invalid: capitalizedNamedOperationsValidatorCases.fail.map(({ code, errors }) => ({ + options, + parserOptions, + code, + errors + })) +}); diff --git a/test/validationRules/index.js b/test/validationRules/index.js index d7efac4..195c114 100644 --- a/test/validationRules/index.js +++ b/test/validationRules/index.js @@ -1,4 +1,5 @@ import './named-operations'; +import './capitalized-named-operations'; import './required-fields'; import './no-deprecated-fields'; import './capitalized-type-name'; From 2b54012f40b821a90258be2e869d3e1f17b3db42 Mon Sep 17 00:00:00 2001 From: Solomon English Date: Fri, 12 Jun 2020 11:38:07 -0700 Subject: [PATCH 2/2] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index f4c417c..5171286 100644 --- a/README.md +++ b/README.md @@ -402,6 +402,8 @@ module.exports = { ### Capitalization of a first letter of Named Operation rule +The Capitalize Named Operation rule validates that all existing operation names are capitalized. + **Pass** ``` query FetchUsername {