feat: introduce graphql linting#2856
Conversation
🦋 Changeset detectedLatest commit: 9c8e4ce The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Performance Benchmark (Lower is Faster)
|
| '@redocly/cli': minor | ||
| --- | ||
|
|
||
| Added initial support for linting GraphQL SDL schema files (`.graphql` / `.gql`). |
There was a problem hiding this comment.
Let's mark it as experimental for now
| "operation-summary": "error", | ||
| }, | ||
| "graphql": { | ||
| "no-empty-servers": "error", |
There was a problem hiding this comment.
Those are unused rules propagated from the root rules config section.
| import type { Config } from './config/index.js'; | ||
| import { initRules } from './config/rules.js'; | ||
| import { isGraphqlRef } from './graphql/extensions.js'; | ||
| import { runGraphqlRules, type InitializedGraphqlRule } from './graphql/run.js'; |
There was a problem hiding this comment.
let's use dynamic import here so it won't load for everyone and slow them down
There was a problem hiding this comment.
I haven't noticed any perf degradation so far. Would you still like to have it imported dynamcally?
7f3750d to
7bd109c
Compare
8723a0d to
73e2aff
Compare
73e2aff to
6bdd8fe
Compare
| ## GraphQL rules | ||
|
|
||
| To expand the linting checks for a GraphQL schema, enable the built-in GraphQL rules. | ||
| Unlike the shared `struct` rule (configured under `rules`), GraphQL-specific built-in rules are configured under the `graphqlRules` section. |
There was a problem hiding this comment.
Looks like we have mismatch in docs. We can also configure graphQL specific rules under rules section, you are listed this below.
| for (const kind of Object.keys(visitor) as Array<keyof GraphqlVisitor>) { | ||
| const handler = visitor[kind]; | ||
| if (!handler) continue; | ||
| const enter = typeof handler === 'function' ? handler : handler.enter; |
There was a problem hiding this comment.
Did you miss the skip visitor or you leave it for the future implementation?
There was a problem hiding this comment.
I haven't found a proper use case for it in GraphQL. We can implement it later if needed.
| "cookie": "^0.7.2", | ||
| "dotenv": "16.4.7", | ||
| "glob": "^13.0.5", | ||
| "graphql": "^16.14.1", |
There was a problem hiding this comment.
I haven't found where we use this package. Could you please explain the purpose of this package?
There was a problem hiding this comment.
For example, in packages/core/src/graphql/visitor.ts or in packages/core/src/graphql/lint-graphql.ts for parsing the docs AST.
There was a problem hiding this comment.
Oh, you mean in the CLI package? Yes, it was a transitive one, not needed anymore.
2b29c2e to
c580a1b
Compare
| config: Config; | ||
| }): NormalizedProblem[] { | ||
| const { document, config } = opts; | ||
| const source = document.source; |
|
|
||
| // GraphQL SDL is not a JSON/YAML tree, so it runs through a separate engine. | ||
| if (isGraphqlRef(document.source.absoluteRef)) { | ||
| return lintGraphqlDocument({ document, config }); |
There was a problem hiding this comment.
I think, that we can add dynamic imports for the GraphQL in the lint command, because now we have esbuild and chunks, so the dynamic import should go to the separate chunk. It should decrease the influence of the GraphQL on the performance.
| @@ -481,6 +487,7 @@ function createAssertionDefinitionSubject(nodeNames: string[]): NodeType { | |||
| type: { | |||
| enum: [...new Set(['any', ...nodeNames, 'SpecExtension'])], | |||
| description: 'REQUIRED. Locates the OpenAPI node type that the lint command evaluates.', | |||
There was a problem hiding this comment.
I am wondering if we add assertions for the GraphQL, do we need to add GraphQL mention there? Or currently it's just an experimental feature?
Co-authored-by: Jacek Łękawa <164185257+JLekawa@users.noreply.github.com>
b69ae8e to
9c8e4ce
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 9c8e4ce. Configure here.
| return [syntaxErrorToProblem(e, source)]; | ||
| } | ||
| throw e; | ||
| } |
There was a problem hiding this comment.
Empty GraphQL file unguarded
Medium Severity
Linting does not treat a wholly empty GraphQL file as a parse failure before parse runs. An empty or whitespace-only body can parse to an empty document and skip the explicit Unexpected <EOF>-style syntax error expected for empty SDL.
Reviewed by Cursor Bugbot for commit 9c8e4ce. Configure here.



What/Why/How?
Added experimental graphql linting.
Reference
Testing
Screenshots (optional)
Check yourself
Security
Note
Medium Risk
New lint path and dependency affect core
lint/resolvebehavior for GraphQL files only; feature is experimental and well-tested but expands the config/rules surface area.Overview
Adds experimental GraphQL SDL linting for
.graphql/.gqlfiles throughredocly lint, wired as a newgraphqlspec alongside existing OpenAPI-style formats.Core engine:
.graphql/.gqlpaths skip YAML parsing and usegraphql-jsto parse SDL and run AST visitors. Built-in rules includestruct(syntax +buildASTSchema/validateSchema),no-unused-types, andtype-description, plusassertionsvia a GraphQL adapter that reuses shared configurable-rule checks on AST kinds (ObjectTypeDefinition, etc.). Thegraphqlruleset omitsno-unresolved-refs; bundle treats GraphQL as non-bundlable.Config & CLI:
graphqlRulesin presets,graphqlplugin rules, config schema extended with GraphQL AST kinds forsubject.type, andcheckIfRulesetExistcounts GraphQL rules. Newgraphqldependency on@redocly/openapi-core.Docs & tests: New lint-graphql guide, lint command cross-links, changeset (minor), unit and e2e coverage for valid/invalid schemas and per-api configurable rule severity.
Reviewed by Cursor Bugbot for commit 9c8e4ce. Bugbot is set up for automated code reviews on this repo. Configure here.