diff --git a/packages/eslint-config/src/configs/graphql.js b/packages/eslint-config/src/configs/graphql.js index 6f475f9..69078fe 100644 --- a/packages/eslint-config/src/configs/graphql.js +++ b/packages/eslint-config/src/configs/graphql.js @@ -12,39 +12,45 @@ export { NAMING_CONVENTION_OPTIONS_GRAPHQL } from '../lib/rule-options.js'; const v3FlatConfigs = 'flatConfigs' in graphqlEslint ? graphqlEslint.flatConfigs : undefined; -export default defineConfig(...node, { - name: 'code-pushup/graphql', - files: GRAPHQL_FILE_PATTERNS, - plugins: { - // @ts-expect-error incompatible meta.docs.category type in rules (`CategoryType | CategoryType[]` not assignable to `string | undefined`) - '@graphql-eslint': graphqlEslint, +export default defineConfig( + ...node, + { + name: 'code-pushup/graphql/node-files-processor', + files: NODE_FILE_PATTERNS, + processor: graphqlEslint.processors.graphql, }, - extends: [ - v3FlatConfigs?.['schema-recommended'] ?? - graphqlEslint.configs['flat/schema-recommended'], - v3FlatConfigs?.['relay'] ?? graphqlEslint.configs['flat/schema-relay'], - { - name: 'code-pushup/graphql/customized', - rules: { - // https://the-guild.dev/graphql/eslint/rules - '@graphql-eslint/description-style': ['warn', { style: 'inline' }], - '@graphql-eslint/no-hashtag-description': 'warn', - '@graphql-eslint/relay-edge-types': [ - 'error', - { listTypeCanWrapOnlyEdgeType: false }, - ], - }, + { + name: 'code-pushup/graphql', + files: GRAPHQL_FILE_PATTERNS, + plugins: { + // @ts-expect-error incompatible meta.docs.category type in rules (`CategoryType | CategoryType[]` not assignable to `string | undefined`) + '@graphql-eslint': graphqlEslint, }, - { - name: 'code-pushup/graphql/disabled', - rules: { - '@graphql-eslint/strict-id-in-types': 'off', + ...(v3FlatConfigs + ? {} + : { languageOptions: { parser: graphqlEslint.parser } }), + extends: [ + v3FlatConfigs?.['schema-recommended'] ?? + graphqlEslint.configs['flat/schema-recommended'], + v3FlatConfigs?.['relay'] ?? graphqlEslint.configs['flat/schema-relay'], + { + name: 'code-pushup/graphql/customized', + rules: { + // https://the-guild.dev/graphql/eslint/rules + '@graphql-eslint/description-style': ['warn', { style: 'inline' }], + '@graphql-eslint/no-hashtag-description': 'warn', + '@graphql-eslint/relay-edge-types': [ + 'error', + { listTypeCanWrapOnlyEdgeType: false }, + ], + }, }, - }, - { - name: 'code-pushup/graphql/node-files-processor', - files: NODE_FILE_PATTERNS, - processor: graphqlEslint.processors.graphql, - }, - ], -}); + { + name: 'code-pushup/graphql/disabled', + rules: { + '@graphql-eslint/strict-id-in-types': 'off', + }, + }, + ], + }, +); diff --git a/packages/eslint-config/tests/configs/graphql.spec.js b/packages/eslint-config/tests/configs/graphql.spec.js index cd7a80a..c86e9c0 100644 --- a/packages/eslint-config/tests/configs/graphql.spec.js +++ b/packages/eslint-config/tests/configs/graphql.spec.js @@ -1,11 +1,14 @@ // @ts-check +import fs from 'node:fs/promises'; +import path from 'node:path'; import { createLintUtils } from '../helpers/lint-utils.js'; describe('graphql config', () => { - const { setup, teardown, loadConfig } = createLintUtils( + const { setup, teardown, loadConfig, lint, cwd } = createLintUtils( 'graphql', '*.graphql', + ['src/schema.ts'], ); beforeAll(setup); @@ -35,6 +38,45 @@ describe('graphql config', () => { ); }); + it('should parse GraphQL files with GraphQL parser', async () => { + const config = await loadConfig('src/schema.graphql'); + expect(config.languageOptions?.parser).toHaveProperty( + 'meta.name', + '@graphql-eslint/parser', + ); + }); + + it.each(['src/schema.ts', 'src/schema.js'])( + 'should attach GraphQL processor to %s', + async filePath => { + const config = await loadConfig(filePath); + expect(config.processor).toBeDefined(); + }, + ); + + it('should lint GraphQL in tagged template of TypeScript file', async () => { + // schema-aware rules need the schema + await fs.writeFile( + path.join(cwd, '.graphqlrc.yml'), + 'schema: src/schema.ts\n', + ); + await fs.writeFile( + path.join(cwd, 'src/schema.ts'), + [ + 'declare const gql: (strings: TemplateStringsArray) => unknown;', + 'export const schema = gql`', + ' type query_root {', + ' id: ID!', + ' }', + '`;', + ].join('\n'), + ); + const [result] = await lint('src/schema.ts'); + expect(result?.messages.map(({ ruleId }) => ruleId)).toContain( + '@graphql-eslint/naming-convention', + ); + }); + it('should have customized rule', async () => { const config = await loadConfig(); expect(config.rules).toHaveProperty('@graphql-eslint/description-style', [ diff --git a/packages/eslint-config/tests/helpers/lint-utils.js b/packages/eslint-config/tests/helpers/lint-utils.js index 05c80a5..7fa4319 100644 --- a/packages/eslint-config/tests/helpers/lint-utils.js +++ b/packages/eslint-config/tests/helpers/lint-utils.js @@ -101,6 +101,7 @@ export default [ meta.docs['requiresTypeChecking'] === true; return { + cwd, setup, teardown, loadConfig,