Skip to content

Commit

Permalink
Fixed merge conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
jtmthf committed Dec 13, 2016
2 parents 17ddb85 + ee36ea2 commit 5e29092
Show file tree
Hide file tree
Showing 7 changed files with 397 additions and 56 deletions.
14 changes: 14 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!--
Thanks for filing a pull request on eslint-plugin-graphql!
Please look at the following checklist to ensure that your PR
can be accepted quickly:
-->

TODO:

- [ ] Make sure all of the significant new logic is covered by tests
- [ ] Rebase your changes on master so that they can be merged easily
- [ ] Make sure all tests pass
- [ ] Update CHANGELOG.md with your change
- [ ] If this was a change that affects the external API, update the README
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# Change log

### vNEXT

- Added `'literal'` option to `env` for when working with `.graphql` and `.gql` files, by [jtmthf in
#36](https://github.com/apollostack/eslint-plugin-graphql/pull/36)

### v0.4.1

- Support for selecting validation rules one by one, by [erydo in
#34](https://github.com/apollostack/eslint-plugin-graphql/pull/34)

### v0.4.0

Expand Down
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,56 @@ module.exports = {
]
}
```

### Selecting Validation Rules

GraphQL validation rules can be configured in the eslint rule's configuration using the `validators` setting. 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"`.

```js
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:
- `ArgumentsOfCorrectType`
- `DefaultValuesOfCorrectType`
- `FieldsOnCorrectType`
- `FragmentsOnCompositeTypes`
- `KnownArgumentNames`
- `KnownDirectives` (*disabled by default in `relay`*)
- `KnownFragmentNames` (*disabled by default in `apollo`, `lokka`, and `relay`*)
- `KnownTypeNames`
- `LoneAnonymousOperation`
- `NoFragmentCycles`
- `NoUndefinedVariables` (*disabled by default in `relay`*)
- `NoUnusedFragments` (*disabled by default in `apollo`, `lokka`, and `relay`*)
- `NoUnusedVariables`
- `OverlappingFieldsCanBeMerged`
- `PossibleFragmentSpreads`
- `ProvidedNonNullArguments` (*disabled by default in `relay`*)
- `ScalarLeafs` (*disabled by default in `relay`*)
- `UniqueArgumentNames`
- `UniqueFragmentNames`
- `UniqueInputFieldNames`
- `UniqueOperationNames`
- `UniqueVariableNames`
- `VariablesAreInputTypes`
- `VariablesInAllowedPosition`
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eslint-plugin-graphql",
"version": "0.4.0",
"version": "0.4.1",
"description": "GraphQL ESLint plugin.",
"author": "Sashko Stubailo",
"main": "lib/index.js",
Expand Down
113 changes: 61 additions & 52 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
parse,
validate,
buildClientSchema,
specifiedRules as allGraphQLValidators,
} from 'graphql';

import {
Expand All @@ -13,48 +14,27 @@ import {
without,
} from 'lodash';

const graphQLValidationRuleNames = [
'UniqueOperationNames',
'LoneAnonymousOperation',
'KnownTypeNames',
'FragmentsOnCompositeTypes',
'VariablesAreInputTypes',
'ScalarLeafs',
'FieldsOnCorrectType',
'UniqueFragmentNames',
//'KnownFragmentNames', -> any interpolation
//'NoUnusedFragments', -> any standalone fragment
'PossibleFragmentSpreads',
'NoFragmentCycles',
'UniqueVariableNames',
'NoUndefinedVariables',
'NoUnusedVariables',
'KnownDirectives',
'KnownArgumentNames',
'UniqueArgumentNames',
'ArgumentsOfCorrectType',
'ProvidedNonNullArguments',
'DefaultValuesOfCorrectType',
'VariablesInAllowedPosition',
'OverlappingFieldsCanBeMerged',
'UniqueInputFieldNames',
];

// Omit these rules when in Relay env
const relayRuleNames = without(graphQLValidationRuleNames,
'ScalarLeafs',
'ProvidedNonNullArguments',
'KnownDirectives',
'NoUndefinedVariables',
);

const graphQLValidationRules = graphQLValidationRuleNames.map((ruleName) => {
return require(`graphql/validation/rules/${ruleName}`)[ruleName];
});

const relayGraphQLValidationRules = relayRuleNames.map((ruleName) => {
return require(`graphql/validation/rules/${ruleName}`)[ruleName];
});
const allGraphQLValidatorNames = allGraphQLValidators.map(rule => rule.name);

// Map of env name to list of rule names.
const envGraphQLValidatorNames = {
apollo: without(allGraphQLValidatorNames,
'KnownFragmentNames',
'NoUnusedFragments',
),
lokka: without(allGraphQLValidatorNames,
'KnownFragmentNames',
'NoUnusedFragments',
),
relay: without(allGraphQLValidatorNames,
'KnownDirectives',
'KnownFragmentNames',
'NoUndefinedVariables',
'NoUnusedFragments',
'ProvidedNonNullArguments',
'ScalarLeafs',
),
};

const internalTag = 'ESLintPluginGraphQLFile';
const gqlFiles = ['gql', 'graphql'];
Expand All @@ -81,6 +61,19 @@ const rules = {
'apollo',
],
},
validators: {
oneOf: [{
type: 'array',
uniqueItems: true,
items: {
enum: allGraphQLValidatorNames,
},
}, {
enum: [
'all',
],
}],
},
tagName: {
type: 'string',
pattern: '^[$_a-zA-Z$_][a-zA-Z0-9$_]+(\\.[a-zA-Z0-9$_]+)?$',
Expand All @@ -101,18 +94,18 @@ const rules = {
const tagNames = new Set();
const tagRules = [];
for (const optionGroup of context.options) {
const {schema, env, tagName} = parseOptions(optionGroup);
const {schema, env, tagName, validators} = parseOptions(optionGroup);
if (tagNames.has(tagName)) {
throw new Error('Multiple options for GraphQL tag ' + tagName);
}
tagNames.add(tagName);
tagRules.push({schema, env, tagName});
tagRules.push({schema, env, tagName, validators});
}
return {
TaggedTemplateExpression(node) {
for (const {schema, env, tagName} of tagRules) {
for (const {schema, env, tagName, validators} of tagRules) {
if (templateExpressionMatchesTag(tagName, node)) {
return handleTemplateTag(node, context, schema, env);
return handleTemplateTag(node, context, schema, env, validators);
}
}
},
Expand All @@ -127,6 +120,7 @@ function parseOptions(optionGroup) {
schemaJsonFilepath, // Or Schema via absolute filepath
env,
tagName: tagNameOption,
validators: validatorNamesOption,
} = optionGroup;

// Validate and unpack schema
Expand Down Expand Up @@ -156,7 +150,22 @@ function parseOptions(optionGroup) {
} else {
tagName = 'gql';
}
return {schema, env, tagName};

// The validator list may be:
// The string 'all' to use all rules.
// An array of rule names.
// null/undefined to use the default rule set of the environment, or all rules.
let validatorNames;
if (validatorNamesOption === 'all') {
validatorNames = allGraphQLValidatorNames;
} else if (validatorNamesOption) {
validatorNames = validatorNamesOption;
} else {
validatorNames = envGraphQLValidatorNames[env] || allGraphQLValidatorNames;
}

const validators = validatorNames.map(name => require(`graphql/validation/rules/${name}`)[name]);
return {schema, env, tagName, validators};
}

function initSchema(json) {
Expand Down Expand Up @@ -191,7 +200,7 @@ function templateExpressionMatchesTag(tagName, node) {
return true;
}

function handleTemplateTag(node, context, schema, env) {
function handleTemplateTag(node, context, schema, env, validators) {
let text;
try {
text = replaceExpressions(node.quasi, context, env);
Expand Down Expand Up @@ -221,10 +230,7 @@ function handleTemplateTag(node, context, schema, env) {
return;
}

const rules = (env === 'relay' ? relayGraphQLValidationRules : graphQLValidationRules);

const validationErrors = schema ? validate(schema, ast, rules) : [];

const validationErrors = schema ? validate(schema, ast, validators) : [];
if (validationErrors && validationErrors.length > 0) {
context.report({
node,
Expand All @@ -236,6 +242,9 @@ function handleTemplateTag(node, context, schema, env) {
}

function locFrom(node, error) {
if (!error.locations || !error.locations.length) {
return;
}
const location = error.locations[0];

let line;
Expand Down
Loading

0 comments on commit 5e29092

Please sign in to comment.