# ts-graphql-plugin: GraphQL types, validation and completion inside the TypeScript editor

> ts-graphql-plugin is a TypeScript Language Service Plugin that brings GraphQL completion, diagnostics, fragment navigation and type generation into the editor, and it also ships a CLI and a webpack transformer. It suits teams writing typed GraphQL clients in TypeScript, and it depends on the schema being reachable at development time.

**Quramy/ts-graphql-plugin** — TypeScript Language Service Plugin for GraphQL developers

- Repository: https://github.com/Quramy/ts-graphql-plugin
- Stars: 756 · Forks: 28
- Language: TypeScript
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/quramy-ts-graphql-plugin

## One plugin, three surfaces: editor, CLI and webpack

ts-graphql-plugin provides functions to help TypeScript GraphQL client development, including auto completion, query validation, type generation and so on. The project description calls it a TypeScript Language Service Plugin for GraphQL developers.

What makes it worth knowing about is that the package exposes the same capability in three different places, and the readme lists them explicitly.

As a TypeScript Language Service extension it gives completion suggestions, GraphQL diagnostics, go to fragment definition, and GraphQL quick info in a tooltip. As a CLI it generates TypeScript type files from the GraphQL operations in your TypeScript sources, and extracts or validates those operations. As a webpack plugin it transforms your queries into GraphQL AST objects statically.

That last one is the most interesting for a build engineer. Turning a query into an AST at build time means the operation is parsed once, ahead of the request, and the runtime is not parsing strings any more. The alternative approach, sending the query text to a server and parsing it there, shifts the parse into the request path.

The audience is a team that writes GraphQL operations inline in TypeScript source, in the style the react-apollo fixture in the repository shows, and that wants the schema to be enforced while typing rather than at request time.

## Getting started: one dev dependency and a tsconfig entry

The setup is short. First you confirm that the project has TypeScript and graphql, with the readme specifying v15.x.0 or later for the GraphQL package.

Install the plugin as a development dependency:

```sh
npm install ts-graphql-plugin -D
```

Then add it to the plugins section of tsconfig.json, giving it the location of your schema:

```json
{
  "compilerOptions": {
    "plugins": [
      {
        "name": "ts-graphql-plugin",
        "schema": "path-or-url-to-your-schema.graphql"
      }
    ]
  }
}
```

There is no further wiring, because the plugin is resolved by name from the plugins array and picks up its options there. The readme says it is ready to go and that you launch your TypeScript IDE, and the screenshot in the readme is a VSCode capture showing the completion in action.

The plugins array in tsconfig.json is the mechanism, and it has a consequence worth remembering: the configuration lives in the file the whole team already commits, so the schema location and any options are versioned with the project rather than living in a personal editor setting.

## The schema option: a local file, a remote URL, or a script that fetches a token

The schema option is required and it accepts more than a file path. The readme documents a union type covering all three shapes:

```ts
type SchemaConfig =
  | string
  | {
      file: {
        path: string;
      };
    }
  | {
      http: {
        url: string;
        method?: string;
        headers?: { [key: string]: string };
      };
    }
  | {
      http: {
        fromScript: string;
      };
    };
```

A plain string is the shorthand for a local SDL file. The file form takes a path. The http form points at an existing GraphQL server with custom headers, and the readme gives the GitHub v4 API as the motivating example, since a company GraphQL endpoint behind a token is the common case:

```json
  "schema": {
    "http": {
      "url": "https://api.github.com/graphql",
      "headers": {
        "Authorization": "Bearer YOUR_GITHUB_API_TOKEN"
      }
    }
  },
```

The third form exists for the case where the token cannot be a static string. The fromScript option names a JavaScript file that returns a RequestSetup or a promise of one, and the readme shows a script that fetches a bearer token from an identity server and resolves the schema configuration with it:

```js
// my-graphql-config.js
module.exports = projectRootPath =>
  new Promise(resolve => {
    fetch('http://localhost/identity-server/connect/token', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: `client_secret=${process.env.MY_CLIENT_SECRET}`,
    })
      .then(response => response.json())
      .then(response => {
        resolve({
          url: 'http://localhost/graphql',
          method: 'POST', // unnecessary, "POST" is default value
          headers: {
            Authorization: `Bearer ${response.access_token}`,
          },
        });
      });
  });
```

The RequestSetup shape is url, an optional method that defaults to POST, and optional headers. The script receives the project root path, which is what lets it resolve its own dependencies.

## The CLI: typegen, extract, validate and report

The command line entry point is:

```sh
npx ts-graphql-plugin <command> [options]
```

If the plugin is installed locally, a short alias is also available: tsgql. The package manifest registers both names, ts-graphql-plugin and tsgql, pointing at the same compiled entry point.

Four commands are documented.

typegen generates TypeScript types from GraphQL operations or fragments in your .ts source files, with a linked example of a generated file for a react-apollo project. extract extracts GraphQL operations and fragments from ts files and writes them to manifest.json. validate validates your GraphQL operations and fragments in your ts files and reports syntax or semantic errors. report extracts operations and fragments and writes them to a Markdown file, again with a linked example output.

The distinction between extract and report is the output format, one JSON manifest and one Markdown document, and they exist for different consumers: the manifest is for tooling, the Markdown file is for people reviewing what a codebase actually asks for.

A useful way to use this is validate first. Running validation over an existing codebase tells you what the current state of your operations is before the editor starts flagging things, which is a gentler way to adopt the plugin than turning diagnostics on and seeing how many errors appear in the editor at once.

## How the plugin finds your operations inside tagged template literals

The mechanism for locating GraphQL documents in TypeScript source is the tag option, and it is optional, with a default value of ["gql", "graphql"]. That default is the whole story for most projects: the plugin looks for template literal strings tagged with gql or graphql and treats their contents as GraphQL documents.

This is why the library is a language service plugin rather than a file watcher. A language service plugin participates in the TypeScript compiler, so it sees the same syntax tree the editor sees, which is what allows it to offer completion inside a tagged template and to report diagnostics at the right position in the file.

The other options in the readme's table of contents follow the same shape of idea. exclude takes a list of paths, with the example excluding __generated__, which is where typegen writes its output and which therefore must not be scanned again or you get a loop. enabledGlobalFragments, localSchemaExtensions and typegen.addons are the remaining documented options, and the readme's table of contents is the index for them.

One built-in type generator addon is documented, typed-query-document, and the addons directory in the repository is where such extensions live. The addon mechanism matters for a team that wants its generated types to carry something extra beyond the plain operation types.

## The webpack transformer and its options

The webpack side of the package is exposed through a separate entry point, the webpack.js file listed in the package manifest files array, so the transformer does not load when you only want the language service part.

The documented webpack plugin options include tsconfigPath, which is optional and points at the TypeScript configuration to use. The transformer options are removeFragmentDefinitions, also optional, and documentTransformers, also optional.

The readme explains that the transformer turns your queries into GraphQL AST objects statically, which is the point of using it in a build. The two options map directly to the two things you would want to control. removeFragmentDefinitions lets you drop fragment definitions from the emitted document, which matters when the fragments are resolved separately and you do not want them inlined into every operation. documentTransformers lets you run your own transformations over the document before it is emitted, which is the hook for anything specific to your schema or your conventions.

A static AST also removes a class of runtime failure. A query string that fails to parse is a runtime error in the request path; a query that fails to parse during the build is a build failure, which is much cheaper to find.

## MIT licensed, version 4, and tested end to end

The project is MIT licensed and the current version is 4.0.5, with v4.0.4 from 2026-02-17 and v4.0.3 from 2024-07-23. The repository is not archived and the last push was on 2026-10-19, so the 4.x line is still being worked on. The package requires Node 18 or above, per the engines field.

The dependency surface is deliberately small. The single runtime dependency is graphql-language-service at version 5.2.1, which is what actually parses and validates the documents; everything else in the manifest is a dev dependency for building and testing the plugin itself.

The test story is the part that shows how a language service plugin is normally verified, and it is not unit tests alone. The test script chains a format check, an eslint run over the TypeScript sources, vitest with coverage, and an end-to-end suite. The end-to-end part runs node e2e/run.js and produces its own coverage with c8, which is the only way to check that a plugin actually works inside a real language service rather than in isolation. The repository also carries a project-fixtures directory with a react-apollo project, and the readme links to a generated file inside that fixture, so the fixtures double as living examples of the typegen output.

The remaining tooling is conventional: eslint, prettier, husky for git hooks, renovate for dependency updates, vitest for the unit tests, and a script that regenerates the table of contents in the readme.

## Conclusion

ts-graphql-plugin fits a TypeScript team that keeps GraphQL documents inside its source files and wants the schema enforced in the editor, with generated types checked in or generated on demand. It does not fit a project that keeps its operations in .graphql files, or a build that cannot reach the schema while compiling. Before adopting it, point the schema option at a local SDL file rather than a remote endpoint, run tsgql validate on your existing operations to see what the current state is, and check that your graphql version is 15.x or later as the readme requires.

## FAQ

### How do I install and configure ts-graphql-plugin?

Install it with npm install ts-graphql-plugin -D, then add an entry to the plugins array in tsconfig.json with the name ts-graphql-plugin and a schema option pointing to your SDL file or a URL. The readme also requires graphql v15.x.0 or later.

### What does the ts-graphql-plugin CLI do?

It provides four commands, typegen to generate TypeScript types from GraphQL operations in .ts files, extract to write operations to manifest.json, validate to report syntax and semantic errors, and report to write operations to a Markdown file. The alias tsgql is available when the plugin is installed locally.

### Can the schema be fetched from a remote GraphQL server?

Yes, the schema option accepts an http form with a url and custom headers, for example pointing at the GitHub v4 API with an Authorization bearer header. For tokens that must be fetched at runtime, the fromScript option names a JavaScript file returning a RequestSetup object with url, an optional method defaulting to POST, and optional headers.

### How does the plugin find GraphQL operations in TypeScript files?

Through the optional tag option, whose default value is ["gql", "graphql"]. The plugin treats template literal strings with those tags as GraphQL documents, and the exclude option keeps generated output such as the __generated__ directory from being scanned again.

### What does the webpack plugin do with my queries?

It transforms your queries into GraphQL AST objects statically, so the document is parsed at build time rather than at request time. The transformer options removeFragmentDefinitions and documentTransformers let you drop fragment definitions from the emitted document and run your own transformations over it.

## Sources

- [Issues](https://github.com/Quramy/ts-graphql-plugin/issues)
- [License: MIT](https://github.com/Quramy/ts-graphql-plugin/blob/main/LICENSE)
- [Quramy/ts-graphql-plugin on GitHub](https://github.com/Quramy/ts-graphql-plugin)
- [README](https://github.com/Quramy/ts-graphql-plugin/blob/main/README.md)
- [Releases](https://github.com/Quramy/ts-graphql-plugin/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/quramy-ts-graphql-plugin
