Skip to content

Commit 2886adf

Browse files
authored
fix passing pluck config via graphql-config#extensions field (#1198)
rename `extensions.graphqlTagPluck` to `extensions.pluckConfig` fix performance regression while using `processor: '@graphql-eslint/graphql'`
1 parent 5e6d617 commit 2886adf

File tree

12 files changed

+121
-117
lines changed

12 files changed

+121
-117
lines changed

.changeset/curly-carrots-call.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@graphql-eslint/eslint-plugin': patch
3+
---
4+
5+
fix passing pluck config via `graphql-config#extensions` field
6+
rename `extensions.graphqlTagPluck` to `extensions.pluckConfig`
7+
fix performance regression while using `processor: '@graphql-eslint/graphql'`

packages/plugin/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@
3434
"prepack": "bob prepack"
3535
},
3636
"dependencies": {
37-
"@babel/code-frame": "^7.16.7",
38-
"@graphql-tools/code-file-loader": "^7.2.14",
39-
"@graphql-tools/graphql-tag-pluck": "^7.2.6",
40-
"@graphql-tools/utils": "^8.6.9",
37+
"@babel/code-frame": "^7.18.6",
38+
"@graphql-tools/code-file-loader": "^7.3.6",
39+
"@graphql-tools/graphql-tag-pluck": "^7.3.6",
40+
"@graphql-tools/utils": "^8.12.0",
4141
"chalk": "^4.1.2",
4242
"debug": "^4.3.4",
43-
"fast-glob": "^3.2.11",
44-
"graphql-config": "^4.3.0",
43+
"fast-glob": "^3.2.12",
44+
"graphql-config": "^4.3.5",
4545
"graphql-depth-limit": "^1.1.0",
4646
"lodash.lowercase": "^4.3.0"
4747
},

packages/plugin/src/graphql-config.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,32 @@ import {
66
loadConfigSync,
77
SchemaPointer,
88
} from 'graphql-config';
9+
import { GraphQLTagPluckOptions } from '@graphql-tools/graphql-tag-pluck';
910
import { CodeFileLoader } from '@graphql-tools/code-file-loader';
1011
import { ParserOptions } from './types';
1112

1213
const debug = debugFactory('graphql-eslint:graphql-config');
1314
let graphQLConfig: GraphQLConfig;
1415

1516
export function loadOnDiskGraphQLConfig(filePath: string): GraphQLConfig {
16-
return loadConfigSync({
17+
const rootDir = dirname(filePath);
18+
const config = loadConfigSync({
1719
// load config relative to the file being linted
18-
rootDir: filePath ? dirname(filePath) : undefined,
20+
rootDir,
1921
throwOnEmpty: false,
2022
throwOnMissing: false,
21-
extensions: [addCodeFileLoaderExtension],
23+
});
24+
if (!config) {
25+
return null;
26+
}
27+
const project = config.getProjectForFile(filePath);
28+
return loadConfigSync({
29+
rootDir,
30+
extensions: [codeFileLoaderExtension(project.extensions.pluckConfig)],
2231
});
2332
}
2433

25-
export function loadGraphQLConfig(options: ParserOptions = {}): GraphQLConfig {
34+
export function loadGraphQLConfig(options: ParserOptions): GraphQLConfig {
2635
// We don't want cache config on test environment
2736
// Otherwise schema and documents will be same for all tests
2837
if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
@@ -53,14 +62,17 @@ export function loadGraphQLConfig(options: ParserOptions = {}): GraphQLConfig {
5362
config: configOptions,
5463
filepath: 'virtual-config',
5564
},
56-
[addCodeFileLoaderExtension]
65+
[codeFileLoaderExtension(options.extensions?.pluckConfig)]
5766
);
5867

5968
return graphQLConfig;
6069
}
6170

62-
const addCodeFileLoaderExtension: GraphQLExtensionDeclaration = api => {
63-
api.loaders.schema.register(new CodeFileLoader());
64-
api.loaders.documents.register(new CodeFileLoader());
65-
return { name: 'graphql-eslint-loaders' };
66-
};
71+
const codeFileLoaderExtension =
72+
(pluckConfig: GraphQLTagPluckOptions): GraphQLExtensionDeclaration =>
73+
api => {
74+
const { schema, documents } = api.loaders;
75+
schema.register(new CodeFileLoader({ pluckConfig }));
76+
documents.register(new CodeFileLoader({ pluckConfig }));
77+
return { name: 'graphql-eslint-loaders' };
78+
};

packages/plugin/src/parser.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,10 @@ const debug = debugFactory('graphql-eslint:parser');
1212

1313
debug('cwd %o', process.cwd());
1414

15-
export function parseForESLint(
16-
code: string,
17-
options: ParserOptions = {}
18-
): GraphQLESLintParseResult {
15+
export function parseForESLint(code: string, options: ParserOptions): GraphQLESLintParseResult {
1916
try {
20-
const filePath = options.filePath || '';
21-
const realFilepath = filePath && getOnDiskFilepath(filePath);
17+
const { filePath } = options;
18+
const realFilepath = getOnDiskFilepath(filePath);
2219

2320
const gqlConfig = loadGraphQLConfig(options);
2421
const projectForFile = realFilepath

packages/plugin/src/processor.ts

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,37 @@ export type Block = Linter.ProcessorFile & {
1212
const blocksMap = new Map<string, Block[]>();
1313

1414
let onDiskConfig: GraphQLConfig;
15+
let pluckConfig: GraphQLTagPluckOptions;
16+
let RELEVANT_KEYWORDS: string[];
1517

1618
export const processor: Linter.Processor<Block | string> = {
1719
supportsAutofix: true,
1820
preprocess(code, filePath) {
19-
onDiskConfig ||= loadOnDiskGraphQLConfig(filePath);
20-
const graphQLTagPluckOptions: GraphQLTagPluckOptions =
21-
onDiskConfig?.getProjectForFile?.(filePath)?.extensions?.graphqlTagPluck;
22-
const {
23-
modules = [],
24-
globalGqlIdentifierName = ['gql', 'graphql'],
25-
gqlMagicComment = 'GraphQL',
26-
} = graphQLTagPluckOptions || {};
21+
if (!pluckConfig) {
22+
onDiskConfig = loadOnDiskGraphQLConfig(filePath);
23+
const {
24+
modules = [],
25+
globalGqlIdentifierName = ['gql', 'graphql'],
26+
gqlMagicComment = 'GraphQL',
27+
} = onDiskConfig?.getProjectForFile(filePath).extensions.pluckConfig || {};
2728

28-
const RELEVANT_KEYWORDS: string[] = [
29-
...new Set(
30-
[
31-
...modules.map(({ identifier }) => identifier),
32-
...asArray(globalGqlIdentifierName),
33-
gqlMagicComment,
34-
].filter(Boolean)
35-
),
36-
];
29+
pluckConfig = {
30+
skipIndent: true,
31+
modules,
32+
globalGqlIdentifierName,
33+
gqlMagicComment,
34+
};
35+
36+
RELEVANT_KEYWORDS = [
37+
...new Set(
38+
[
39+
...modules.map(({ identifier }) => identifier),
40+
...asArray(globalGqlIdentifierName),
41+
gqlMagicComment,
42+
].filter(Boolean)
43+
),
44+
];
45+
}
3746

3847
if (RELEVANT_KEYWORDS.every(keyword => !code.includes(keyword))) {
3948
return [code];
@@ -43,10 +52,7 @@ export const processor: Linter.Processor<Block | string> = {
4352
const extractedDocuments = parseCode({
4453
code,
4554
filePath,
46-
options: {
47-
skipIndent: true,
48-
...graphQLTagPluckOptions,
49-
},
55+
options: pluckConfig,
5056
});
5157

5258
const blocks: Block[] = extractedDocuments.map(item => ({

packages/plugin/src/schema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const debug = debugFactory('graphql-eslint:schema');
1111

1212
export function getSchema(
1313
projectForFile: GraphQLProjectConfig,
14-
options: ParserOptions = {}
14+
options: Omit<ParserOptions, 'filePath'> = {}
1515
): Schema {
1616
const schemaKey = asArray(projectForFile.schema).sort().join(',');
1717

packages/plugin/src/testkit.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ function applyFix(code: string, { range, text }: Rule.Fix): string {
3737
export class GraphQLRuleTester extends RuleTester {
3838
config: {
3939
parser: string;
40-
parserOptions: ParserOptions;
40+
parserOptions: Omit<ParserOptions, 'filePath'>;
4141
};
4242

43-
constructor(parserOptions: ParserOptions = {}) {
43+
constructor(parserOptions: Omit<ParserOptions, 'filePath'> = {}) {
4444
const config = {
4545
parser: require.resolve('@graphql-eslint/eslint-plugin'),
4646
parserOptions: {

packages/plugin/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export interface ParserOptions {
2222
};
2323
graphQLParserOptions?: Omit<GraphQLParseOptions, 'noLocation'>;
2424
skipGraphQLConfig?: boolean;
25-
filePath?: string;
25+
filePath: string;
2626
}
2727

2828
export type ParserServices = {

packages/plugin/tests/processor-with-graphql-config.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ jest.mock('../src/graphql-config', () => ({
44
loadOnDiskGraphQLConfig: jest.fn(() => ({
55
getProjectForFile: () => ({
66
extensions: {
7-
graphqlTagPluck: {
7+
pluckConfig: {
88
modules: [{ name: 'custom-gql-tag', identifier: 'custom' }],
99
gqlMagicComment: 'CustoM',
1010
},

packages/plugin/tests/schema.spec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ describe('schema', () => {
1212
const schemaOnDisk = readFileSync(SCHEMA_GRAPHQL_PATH, 'utf8');
1313

1414
const testSchema = (schema: string) => {
15-
const gqlConfig = loadGraphQLConfig({ schema });
15+
const gqlConfig = loadGraphQLConfig({ schema, filePath: '' });
1616
const graphQLSchema = getSchema(gqlConfig.getDefault());
1717
expect(graphQLSchema).toBeInstanceOf(GraphQLSchema);
1818

@@ -87,6 +87,7 @@ describe('schema', () => {
8787
schema: {
8888
[schemaUrl]: schemaOptions,
8989
},
90+
filePath: '',
9091
});
9192
const error = getSchema(gqlConfig.getDefault()) as Error;
9293
expect(error).toBeInstanceOf(Error);
@@ -95,7 +96,7 @@ describe('schema', () => {
9596

9697
// https://github.com/B2o5T/graphql-eslint/blob/master/docs/parser-options.md#schemaoptions
9798
it('with `parserOptions.schemaOptions`', () => {
98-
const gqlConfig = loadGraphQLConfig({ schema: schemaUrl });
99+
const gqlConfig = loadGraphQLConfig({ schema: schemaUrl, filePath: '' });
99100
const error = getSchema(gqlConfig.getDefault(), { schemaOptions }) as Error;
100101
expect(error).toBeInstanceOf(Error);
101102
expect(error.message).toMatch('"authorization":"Bearer Foo"');
@@ -105,7 +106,7 @@ describe('schema', () => {
105106

106107
describe('schema loading', () => {
107108
it('should return Error', () => {
108-
const gqlConfig = loadGraphQLConfig({ schema: 'not-exist.gql' });
109+
const gqlConfig = loadGraphQLConfig({ schema: 'not-exist.gql', filePath: '' });
109110
const error = getSchema(gqlConfig.getDefault()) as Error;
110111
expect(error).toBeInstanceOf(Error);
111112
expect(error.message).toMatch(
@@ -115,9 +116,8 @@ describe('schema', () => {
115116
});
116117

117118
it('should load the graphql-config rc file relative to the linted file', () => {
118-
const schema = resolve(__dirname, 'mocks/using-config/schema.graphql');
119119
const gqlConfig = loadGraphQLConfig({
120-
schema,
120+
schema: resolve(__dirname, 'mocks/using-config/schema.graphql'),
121121
filePath: resolve(__dirname, 'mocks/using-config/test.graphql'),
122122
});
123123

0 commit comments

Comments
 (0)