Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/strong-otters-mate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-eslint/eslint-plugin': patch
---

add an example with custom graphql rules
21 changes: 21 additions & 0 deletions examples/custom-rules/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import graphqlPlugin from '@graphql-eslint/eslint-plugin';
import { rule } from './my-rule.js';

export default [
{
files: ['**/*.graphql'],
languageOptions: {
parser: graphqlPlugin.parser,
},
plugins: {
'@internal': {
rules: {
'my-rule': rule,
},
},
},
rules: {
'@internal/my-rule': 'error',
},
},
];
14 changes: 14 additions & 0 deletions examples/custom-rules/my-rule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const rule = {
create(context) {
return {
OperationDefinition(node) {
if (!node.name?.value) {
context.report({
node,
message: 'Oops, name is required!',
});
}
},
};
},
};
18 changes: 18 additions & 0 deletions examples/custom-rules/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "@graphql-eslint/example-custom-rules",
"version": "0.0.0",
"type": "module",
"repository": "https://github.com/dimaMachina/graphql-eslint",
"author": "Dimitri POSTOLOV <[email protected]>",
"private": true,
"scripts": {
"lint": "eslint --cache ."
},
"dependencies": {
"graphql": "16.9.0"
},
"devDependencies": {
"@graphql-eslint/eslint-plugin": "4.1.0",
"eslint": "9.15.0"
}
}
3 changes: 3 additions & 0 deletions examples/custom-rules/test.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
query {
foo
}
20 changes: 20 additions & 0 deletions packages/plugin/__tests__/__snapshots__/examples.spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -2133,3 +2133,23 @@ exports[`Examples > should work with \`graphql-config\` 2`] = `
},
]
`;

exports[`Examples > should work with custom rules 1`] = `
[
{
filePath: examples/custom-rule/test.graphql,
messages: [
{
column: 1,
endColumn: 13,
endLine: 1,
line: 1,
message: Oops, name is required!,
nodeType: OperationDefinition,
ruleId: @internal/my-rule,
severity: 2,
},
],
},
]
`;
7 changes: 7 additions & 0 deletions packages/plugin/__tests__/examples.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ describe('Examples', () => {
const cwd = path.join(CWD, 'examples', 'multiple-projects-graphql-config');
testESLintOutput(cwd, 4);
});

it('should work with custom rules', () => {
const cwd = path.join(CWD, 'examples', 'custom-rules');
const flatResults = getFlatESLintOutput(cwd);
expect(normalizeResults(flatResults)).toMatchSnapshot();
expect(countErrors(flatResults)).toBe(1);
});
});

function testESLintOutput(cwd: string, errorCount: number): void {
Expand Down
11 changes: 11 additions & 0 deletions website/content/docs/usage/custom-rules.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
sidebarTitle: Custom GraphQL Rules
---

# Usage with custom GraphQL rules

<ESLintConfigs gitFolder="custom-rules" additionalFiles={{ 'Custom GraphQL Rule': 'my-rule.js' }} />

> [!TIP]
>
> Check out the [custom rules](/docs/custom-rules) guide to learn how to create your own rules.
5 changes: 4 additions & 1 deletion website/content/docs/usage/graphql.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ icon: GraphQLIcon

# Usage with `.graphql` files

<ESLintConfigs gitFolder="graphql-config" graphqlConfigFile="graphql.config.js" />
<ESLintConfigs
gitFolder="graphql-config"
additionalFiles={{ 'GraphQL Config': 'graphql.config.js' }}
/>
2 changes: 1 addition & 1 deletion website/content/docs/usage/js.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ export default [

---

<ESLintConfigs gitFolder="code-file" graphqlConfigFile="graphql.config.js" />
<ESLintConfigs gitFolder="code-file" additionalFiles={{ 'GraphQL Config': 'graphql.config.js' }} />
5 changes: 4 additions & 1 deletion website/content/docs/usage/multiple-projects.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ icon: StackIcon

# Usage to lint different schemas

<ESLintConfigs gitFolder="multiple-projects-graphql-config" graphqlConfigFile="graphql.config.ts" />
<ESLintConfigs
gitFolder="multiple-projects-graphql-config"
additionalFiles={{ 'GraphQL Config': 'graphql.config.ts' }}
/>
2 changes: 1 addition & 1 deletion website/content/docs/usage/schema-and-operations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ icon: HalfIcon

# Usage to lint both schema/operations

<ESLintConfigs gitFolder="monorepo" graphqlConfigFile="graphql.config.js" />
<ESLintConfigs gitFolder="monorepo" additionalFiles={{ 'GraphQL Config': 'graphql.config.js' }} />
52 changes: 32 additions & 20 deletions website/mdx-components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,52 @@ import {
} from '@theguild/components/server';

const docsComponents = getDocsMDXComponents({
async ESLintConfigs({ gitFolder, graphqlConfigFile = '' }) {
async ESLintConfigs({
gitFolder,
additionalFiles,
}: {
gitFolder: string;
additionalFiles: Record<string, string>;
}) {
const user = 'dimaMachina';
const repo = 'graphql-eslint';
const branch = 'master';
const docsPath = path.join(process.cwd(), '..', 'examples', gitFolder);
const { ext } = path.parse(graphqlConfigFile);

const graphqlConfig =
graphqlConfigFile &&
`
## GraphQL Config
const promises = Object.entries({
...additionalFiles,
'ESLint Flat Config': 'eslint.config.js',
}).map(async ([heading, filePath]) => {
const { ext } = path.parse(filePath);
return `## ${heading}

\`\`\`${ext.slice(1)} filename="${graphqlConfigFile}"
${(await fs.readFile(`${docsPath}/${graphqlConfigFile}`, 'utf8')).trim()}
\`\`\`
`;
\`\`\`${ext.slice(1)} filename="${filePath}"
${(await fs.readFile(`${docsPath}/${filePath}`, 'utf8')).trim()}
\`\`\``;
});
const files = await Promise.all(promises);

const hasLegacyConfig = await fs
.access(`${docsPath}/.eslintrc.cjs`)
.then(() => true)
.catch(() => '');

return (
<MDXRemote
compiledSource={await compileMdx(`
> [!NOTE]
>
> Check out
> [the official examples](https://github.com/${user}/${repo}/tree/${branch}/examples/${gitFolder})
> [the official example${hasLegacyConfig && 's'}](https://github.com/${user}/${repo}/tree/${branch}/examples/${gitFolder})
> for
> [ESLint Flat Config](https://github.com/${user}/${repo}/blob/${branch}/examples/${gitFolder}/eslint.config.js)
> or
> [ESLint Legacy Config](https://github.com/${user}/${repo}/blob/${branch}/examples/${gitFolder}/.eslintrc.cjs)
> .
${hasLegacyConfig ? `> or [ESLint Legacy Config](https://github.com/${user}/${repo}/blob/${branch}/examples/${gitFolder}/.eslintrc.cjs).` : '>.'}

${graphqlConfig}
## ESLint Flat Config
\`\`\`js filename="eslint.config.js"
${(await fs.readFile(`${docsPath}/eslint.config.js`, 'utf8')).trim()}
\`\`\`
${files.join('\n')}

${
hasLegacyConfig &&
`
## ESLint Legacy Config

> [!WARNING]
Expand All @@ -52,7 +62,9 @@ ${(await fs.readFile(`${docsPath}/eslint.config.js`, 'utf8')).trim()}

\`\`\`js filename=".eslintrc.cjs"
${(await fs.readFile(`${docsPath}/.eslintrc.cjs`, 'utf8')).trim()}
\`\`\``)}
\`\`\``
}
`)}
/>
);
},
Expand Down
Loading