ESLint Plugin
@graphql-analyzer/eslint-plugin runs the same lint rules as the CLI and LSP,
but inside ESLint. It’s a drop-in replacement for
@graphql-eslint/eslint-plugin —
same plugin names, same rule names, same flat-config preset names. The Rust
analyzer does the real work via a native addon, so performance matches the CLI.
Requirements
Section titled “Requirements”- Node.js 18 or later
- ESLint 8.40+ or 9.x (flat config only)
Installation
Section titled “Installation”npm install --save-dev @graphql-analyzer/eslint-pluginDuring the alpha, install with the alpha dist-tag:
npm install --save-dev @graphql-analyzer/eslint-plugin@alphaThe native addon is distributed as platform-specific optional dependencies
(darwin-arm64, darwin-x64, linux-x64-gnu, linux-arm64-gnu,
win32-x64-msvc). npm installs the one matching your machine automatically.
import graphql from "@graphql-analyzer/eslint-plugin";
export default [ // 1. Lint `.graphql` files directly. This block also handles the virtual // `.graphql` blocks the processor extracts from JS/TS/SFC hosts (block // paths look like `path/to/component.tsx/0_document.graphql`). { files: ["**/*.graphql"], languageOptions: { parser: graphql.parser, }, plugins: { "@graphql-analyzer": graphql, }, rules: { "@graphql-analyzer/no-anonymous-operations": "error", "@graphql-analyzer/no-duplicate-fields": "error", "@graphql-analyzer/no-hashtag-description": "warn", }, }, // 2. Wire the named processor onto every host extension that may carry // embedded GraphQL. Vue, Svelte, and Astro files are supported by the // native extractor — list their extensions here alongside JS/TS so the // processor sees them. { files: ["**/*.{js,jsx,mjs,cjs,ts,tsx,vue,svelte,astro}"], plugins: { "@graphql-analyzer": graphql, }, processor: "@graphql-analyzer/graphql", },];The native addon detects embedded GraphQL in JavaScript, TypeScript, Vue
single-file components, Svelte components, and Astro components.
Diagnostics are reported at their original source position so gql tagged
templates don’t need a separate file.
Embedded extraction matrix
Section titled “Embedded extraction matrix”| Extension | What gets scanned | Host parser you’ll likely want |
|---|---|---|
.js, .jsx, .mjs, .cjs | The whole file | None (espree, ESLint’s default, handles it) |
.ts, .tsx | The whole file | @typescript-eslint/parser |
.vue | All <script> and <script setup> blocks | vue-eslint-parser |
.svelte | All <script> blocks (including context="module") | svelte-eslint-parser |
.astro | The frontmatter (between --- fences) | astro-eslint-parser |
The lang attribute on <script> tags is honored — lang="ts" is parsed
as TypeScript, anything else as JavaScript. Astro frontmatter is always
TypeScript per Astro’s own conventions.
Host parsers for non-JS files
Section titled “Host parsers for non-JS files”ESLint’s default parser (espree) only understands JavaScript. Without a host parser configured, ESLint reports a fatal “Parsing error” on the host file itself, which sits alongside the GraphQL diagnostics from the processor. The embedded GraphQL is still linted — but you’ll usually want a real host parser so the rest of your ESLint config (TypeScript rules, framework rules, etc.) can run too. Add one in a separate config block per host:
import graphql from "@graphql-analyzer/eslint-plugin";import tsParser from "@typescript-eslint/parser";import vueParser from "vue-eslint-parser";import svelteParser from "svelte-eslint-parser";import astroParser from "astro-eslint-parser";
export default [ // GraphQL block + processor block (see "Usage" above). /* ... */
// Host parsers — match each extension to the parser that understands it. // The processor still does the embedded extraction; these blocks just give // ESLint a working host AST so the rest of your config has something to // run against. { files: ["**/*.{ts,tsx}"], languageOptions: { parser: tsParser }, }, { files: ["**/*.vue"], languageOptions: { parser: vueParser, parserOptions: { parser: tsParser }, }, }, { files: ["**/*.svelte"], languageOptions: { parser: svelteParser, parserOptions: { parser: tsParser }, }, }, { files: ["**/*.astro"], languageOptions: { parser: astroParser }, },];We intentionally don’t bundle these parsers — pick the ones that already match the rest of your project’s ESLint config.
Configuration
Section titled “Configuration”Rules pick up their configuration from .graphqlrc.yaml (or any supported
graphql-config file) in the nearest ancestor directory of the file being
linted:
schema: "schema.graphql"documents: "src/**/*.graphql"extensions: graphql-analyzer: lint: rules: noHashtagDescription: warn noAnonymousOperations: error noDuplicateFields: errorThis is the same config format the CLI and LSP use, so your editor, CI, and ESLint all see the same rules.
Presets
Section titled “Presets”import graphql from "@graphql-analyzer/eslint-plugin";
export default [ { files: ["**/*.graphql"], languageOptions: { parser: graphql.parser }, plugins: { "@graphql-analyzer": graphql }, rules: graphql.configs["flat/schema-recommended"].rules, },];Available presets:
flat/schema-recommended— sensible defaults for schema filesflat/operations-recommended— sensible defaults for operation documentsflat/schema-all— all schema rules enabledflat/schema-relay— Relay-specific schema rulesflat/operations-all— all operation rules enabled
Migrating from @graphql-eslint/eslint-plugin
Section titled “Migrating from @graphql-eslint/eslint-plugin”The migration is a find-and-replace:
@graphql-eslint/eslint-plugin→@graphql-analyzer/eslint-plugin@graphql-eslint→@graphql-analyzer(plugin names, rule prefixes)
Rule names, rule options, and preset names are identical.
import graphqlPlugin from "@graphql-eslint/eslint-plugin";import graphqlPlugin from "@graphql-analyzer/eslint-plugin";
export default [ { files: ["**/*.graphql"], languageOptions: { parser: graphqlPlugin.parser }, plugins: { "@graphql-eslint": graphqlPlugin }, plugins: { "@graphql-analyzer": graphqlPlugin }, rules: { "@graphql-eslint/no-anonymous-operations": "error", "@graphql-analyzer/no-anonymous-operations": "error", }, },];Rule parity with @graphql-eslint/eslint-plugin
Section titled “Rule parity with @graphql-eslint/eslint-plugin”The plugin’s test suite diffs its rule set against @graphql-eslint/eslint-plugin
and fails CI on unexpected divergence — migration stays a find-and-replace.
Current intentional gaps:
- Validation rules (from
graphql-js’sspecifiedRules:known-type-names,fields-on-correct-type,no-undefined-variables, etc.) aren’t exposed as lint rules. They run as part of the analyzer’s validation pass instead.
See packages/eslint-plugin/test/parity.test.mjs for the full allowlist.
Known limitations (alpha)
Section titled “Known limitations (alpha)”- ESLint legacy config (
.eslintrc) is not supported — flat config only. - Autofix coverage matches upstream:
alphabetizeonly. Other shared rules shipsuggest(suggestions) upstream and are not yet wired through our ESLint shim.
See the rules catalog for the full list of rules available.