Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop Node 8. Support GraphQL 15. Update Babel 7 & ESLint 6.8 #271

Merged
merged 13 commits into from
May 29, 2020
4 changes: 4 additions & 0 deletions .babelrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
presets: ['@babel/preset-env'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't specify targets here or browserslist in the package.json, this transpiles to ES2015 (ES6) (Source). That's probably fine, but if we're specifying engines at >= 10, I guess we can go ahead and bump the transpilation target. I've done that in 3ecf7de.

plugins: ['@babel/plugin-transform-runtime'],
};
2 changes: 1 addition & 1 deletion .tav.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

graphql:
versions: ^0.12.0 || ^0.13.0 || ^14.0.0
versions: ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0
commands: mocha test/index.js
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: node_js
node_js:
- "8"
- "10"
- "12"
install:
- npm install

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### vNEXT

- Improve identity template literal tag docs. [PR #254](https://github.com/apollographql/eslint-plugin-graphql/pull/254) by [Jayden Seric](https://github.com/jaydenseric).
- Add support for GraphQL 15. Update all `devDependencies` - upgrades the project to use Babel 7 and ESLint 6. [PR #271](https://github.com/apollographql/eslint-plugin-graphql/pull/271) by [Scott Taylor](https://github.com/staylor).

### v3.1.1

Expand Down
10,812 changes: 8,028 additions & 2,784 deletions package-lock.json

Large diffs are not rendered by default.

41 changes: 19 additions & 22 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"scripts": {
"test": "tav --ci && mocha test/index.js",
"prepublish": "babel ./src --ignore test --out-dir ./lib",
"pretest": "node test/updateSchemaJson.js",
"pretest": "babel-node test/updateSchemaJson.js",
"tav": "tav",
"lint": "eslint 'src/**/*.js' 'test/**/*.js'"
},
Expand All @@ -17,39 +17,36 @@
"url": "git+https://github.com/apollostack/eslint-plugin-graphql.git"
},
"devDependencies": {
"babel-cli": "6.26.0",
"babel-core": "6.26.3",
"babel-eslint": "10.0.1",
"babel-plugin-transform-runtime": "6.23.0",
"babel-preset-es2015": "6.24.1",
"babel-preset-stage-0": "6.24.1",
"eslint": "5.16.0",
"graphql": "14.4.2",
"graphql-tools": "4.0.5",
"mocha": "6.2.0",
"pretty-quick": "1.11.1",
"@babel/cli": "7.10.1",
"@babel/core": "7.10.1",
"@babel/node": "7.10.1",
"@babel/plugin-transform-runtime": "7.10.1",
"@babel/preset-env": "7.10.1",
"@babel/register": "7.9.0",
"babel-eslint": "10.1.0",
"eslint": "6.8.0",
"graphql": "15.0.0",
"graphql-tools": "6.0.3",
"mocha": "7.2.0",
"pretty-quick": "2.0.1",
"test-all-versions": "4.1.1"
},
"babel": {
"presets": [
"es2015",
"stage-0"
]
},
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged"
}
},
"engines": {
"node": ">=6.0"
"node": ">=10.0"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a note about dropping support for Node.js to the changelog after merging.

},
"license": "MIT",
"dependencies": {
"graphql-config": "^2.0.1",
"lodash": "^4.11.1"
"@babel/runtime": "^7.10.0",
"graphql-config": "^3.0.2",
"lodash.flatten": "^4.4.0",
"lodash.without": "^4.4.0"
},
"peerDependencies": {
"graphql": "^0.12.0 || ^0.13.0 || ^14.0.0"
"graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0"
}
}
69 changes: 50 additions & 19 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import {
specifiedRules as allGraphQLValidators
} from "graphql";

import { flatten, keys, reduce, without, includes } from "lodash";
import flatten from "lodash.flatten";
import without from "lodash.without";

import { getGraphQLConfig, ConfigNotFoundError } from "graphql-config";
import { loadConfigSync, ConfigNotFoundError, ProjectNotFoundError } from "graphql-config";

import * as customRules from "./customGraphQLValidationRules";
import { internalTag } from "./constants";
Expand All @@ -21,34 +22,54 @@ const envGraphQLValidatorNames = {
apollo: without(
allGraphQLValidatorNames,
"KnownFragmentNames",
"NoUnusedFragments"
"NoUnusedFragments",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR didn't introduce it this, but worth noting that this technique of excluding by validator rules by the string-form of their name has broken down once before when subjected to minification since the functions in graphql had been minified themselves. See apollographql/apollo-server#3335.

Because of its role in the ecosystem (in dev tooling) I don't suspect this package or its dependencies will be subject to minification, but just noting. Definitely not asking for a change. 😄

// `graphql`@15
"KnownFragmentNamesRule",
"NoUnusedFragmentsRule"
),
lokka: without(
allGraphQLValidatorNames,
"KnownFragmentNames",
"NoUnusedFragments"
"NoUnusedFragments",
// `graphql`@15
"KnownFragmentNamesRule",
"NoUnusedFragmentsRule"
),
fraql: without(
allGraphQLValidatorNames,
"KnownFragmentNames",
"NoUnusedFragments"
"NoUnusedFragments",
// `graphql`@15
"KnownFragmentNamesRule",
"NoUnusedFragmentsRule"
),
relay: without(
allGraphQLValidatorNames,
"KnownDirectives",
"KnownFragmentNames",
"NoUndefinedVariables",
"NoUnusedFragments",
// `graphql`@15
"KnownDirectivesRule",
"KnownFragmentNamesRule",
"NoUndefinedVariablesRule",
"NoUnusedFragmentsRule",
// `graphql` < 14
"ProvidedNonNullArguments",
// `graphql`@14
"ProvidedRequiredArguments",
"ScalarLeafs"
"ScalarLeafs",
// `graphql`@15
"ProvidedRequiredArgumentsRule",
"ScalarLeafsRule"
),
literal: without(
allGraphQLValidatorNames,
"KnownFragmentNames",
"NoUnusedFragments"
"NoUnusedFragments",
// `graphql`@15
"KnownFragmentNamesRule",
"NoUnusedFragmentsRule"
)
};

Expand Down Expand Up @@ -268,23 +289,34 @@ function parseOptions(optionGroup, context) {
schema = initSchemaFromString(schemaString);
} else {
try {
const config = getGraphQLConfig(path.dirname(context.getFilename()));
const config = loadConfigSync({
rootDir: path.resolve(
process.cwd(),
path.dirname(context.getFilename())
)
});
let projectConfig;
if (projectName) {
projectConfig = config.getProjects()[projectName];
projectConfig = config.getProject(projectName);
if (!projectConfig) {
throw new Error(
`Project with name "${projectName}" not found in ${config.configPath}.`
`Project with name "${projectName}" not found in ${config.filepath}.`
);
}
} else {
projectConfig = config.getConfigForFile(context.getFilename());
try {
projectConfig = config.getProjectForFile(context.getFilename());
} catch (e) {
if (!(e instanceof ProjectNotFoundError)) {
throw e;
}
}
}
if (projectConfig) {
const key = `${config.configPath}[${projectConfig.projectName}]`;
const key = `${config.filepath}[${projectConfig.name}]`;
schema = projectCache[key];
if (!schema) {
schema = projectConfig.getSchema();
schema = projectConfig.getSchemaSync();
projectCache[key] = schema;
}
}
Expand All @@ -294,7 +326,7 @@ function parseOptions(optionGroup, context) {
} catch (e) {
if (e instanceof ConfigNotFoundError) {
throw new Error(
"Must provide .graphqlconfig file or pass in `schemaJson` option " +
"Must provide GraphQL Config file or pass in `schemaJson` option " +
"with schema object or `schemaJsonFilepath` with absolute path to the json file."
);
}
Expand Down Expand Up @@ -385,14 +417,13 @@ const gqlProcessor = {
},
postprocess: function(messages) {
// only report graphql-errors
return flatten(messages).filter(message => {
return includes(keys(rules).map(key => `graphql/${key}`), message.ruleId);
});
return flatten(messages).filter(message =>
Object.keys(rules).map(key => `graphql/${key}`).includes(message.ruleId)
);
}
};

export const processors = reduce(
gqlFiles,
export const processors = gqlFiles.reduce(
(result, value) => {
return { ...result, [`.${value}`]: gqlProcessor };
},
Expand Down
3 changes: 2 additions & 1 deletion test/customTagName.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import schemaJson from './schema.json';
import { isGraphQL15 } from './helpers';

import {
rule,
Expand All @@ -25,7 +26,7 @@ ruleTester.run('custom tag name', rule, {
parserOptions,
code: 'const x = myGraphQLTag``',
errors: [{
message: 'Syntax Error: Unexpected <EOF>',
message: isGraphQL15 ? 'Syntax Error: Unexpected <EOF>.' : 'Syntax Error: Unexpected <EOF>',
type: 'TaggedTemplateExpression'
}]
},
Expand Down
3 changes: 2 additions & 1 deletion test/default.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isGraphQL15 } from './helpers';
import schemaJson from './schema.json';

import {
Expand Down Expand Up @@ -45,7 +46,7 @@ ruleTester.run('default options', rule, {
parserOptions,
code: 'const x = gql``',
errors: [{
message: 'Syntax Error: Unexpected <EOF>',
message: isGraphQL15 ? 'Syntax Error: Unexpected <EOF>.' : 'Syntax Error: Unexpected <EOF>',
type: 'TaggedTemplateExpression'
}]
},
Expand Down
3 changes: 2 additions & 1 deletion test/env/apollo.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isGraphQL15 } from '../helpers';
import schemaJson from '../schema.json';

import {
Expand Down Expand Up @@ -34,7 +35,7 @@ ruleTester.run('apollo', rule, {
parserOptions,
code: 'const x = gql`query }{ ${x}`',
errors: [{
message: 'Syntax Error: Expected {, found }',
message: isGraphQL15 ? 'Syntax Error: Expected "{", found "}".' : 'Syntax Error: Expected {, found }',
type: 'TaggedTemplateExpression'
}]
}
Expand Down
5 changes: 4 additions & 1 deletion test/env/lokka.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isGraphQL15 } from '../helpers';
import schemaJson from '../schema.json';

import {
Expand Down Expand Up @@ -111,7 +112,9 @@ ruleTester.run('lokka', rule, {
\`);
`,
errors: [{
message: 'Unknown argument "wrongArg" on field "director" of type "Film".',
message: isGraphQL15 ?
'Unknown argument "wrongArg" on field "Film.director".' :
'Unknown argument "wrongArg" on field "director" of type "Film".',
type: 'TaggedTemplateExpression',
line: 5,
column: 22
Expand Down
2 changes: 1 addition & 1 deletion test/env/relay.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const options = [
];

// Need this to support statics
const parser = 'babel-eslint';
const parser = require.resolve('babel-eslint');

ruleTester.run('relay', rule, {
valid: [
Expand Down
12 changes: 0 additions & 12 deletions test/graphqlconfig/multiproject-literal/.graphqlconfig

This file was deleted.

12 changes: 12 additions & 0 deletions test/graphqlconfig/multiproject-literal/graphql.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"projects": {
"gql": {
"schema": "../../schema.graphql",
"include": ["first.graphql"]
},
"swapi": {
"schema": "../../second-schema.graphql",
"include": ["second.graphql"]
}
}
}
4 changes: 2 additions & 2 deletions test/graphqlconfig/multiproject/.graphqlconfig
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"projects": {
"gql": {
"schemaPath": "../../schema.graphql"
"schema": "../../schema.graphql"
},
"swapi": {
"schemaPath": "../../second-schema.graphql"
"schema": "../../second-schema.graphql"
}
}
}
3 changes: 0 additions & 3 deletions test/graphqlconfig/simple/.graphqlconfig

This file was deleted.

3 changes: 3 additions & 0 deletions test/graphqlconfig/simple/graphql.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"schema": "../../schema.graphql"
}
16 changes: 13 additions & 3 deletions test/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,26 @@ import { rules } from '../src';
import { RuleTester } from 'eslint';
import schemaJson from './schema.json';
import path from 'path';
import { printSchema, buildClientSchema, specifiedRules as allGraphQLValidators } from 'graphql';
import * as graphql from 'graphql';

const { printSchema, buildClientSchema, specifiedRules: allGraphQLValidators } = graphql;

export const isGraphQL15 = graphql.versionInfo && graphql.versionInfo.major >= 15;

export const schemaJsonFilepath = path.resolve(__dirname, './schema.json');
export const secondSchemaJsonFilepath = path.resolve(__dirname, './second-schema.json');
export const schemaString = printSchema(buildClientSchema(schemaJson.data))

const allGraphQLValidatorNames = allGraphQLValidators.map(rule => rule.name);
export const requiredArgumentRuleName = allGraphQLValidatorNames.includes('ProvidedRequiredArguments') ?
'ProvidedRequiredArguments':'ProvidedNonNullArguments';

let requiredArgumentRule = 'ProvidedNonNullArguments';
if (allGraphQLValidatorNames.includes('ProvidedRequiredArgumentsRule')) {
requiredArgumentRule = 'ProvidedRequiredArgumentsRule';
} else if (allGraphQLValidatorNames.includes('ProvidedRequiredArguments')) {
requiredArgumentRule = 'ProvidedRequiredArguments';
}

export const requiredArgumentRuleName = requiredArgumentRule;

// Init rule

Expand Down
8 changes: 1 addition & 7 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
// This file cannot be written with ECMAScript 2015 because it has to load
// the Babel require hook to enable ECMAScript 2015 features!
require('babel-core/register');
require('babel-core').transform('code', {
plugins: ['transform-runtime']
});
require('@babel/register');

// The tests, however, can and should be written with ECMAScript 2015.
require('./makeProcessors');
require('./graphqlconfig/');
require('./env');
Expand Down
Loading