Catch the highlights of GraphQLConf 2023! Click for recordings. Or check out our recap blog post.
Docs
Writing Plugins
Plugin structure

Write your first Plugin

Basic Plugin

To get started with writing your GraphQL Code-Generator plugin, start by creating a simple my-plugin.js file in your project, with the following content:

my-plugin.js
module.exports = {
  plugin(schema, documents, config) {
    return 'Hi!'
  }
}

The exported object should match the CodegenPlugin interface.

Now, let's try to load and use it with the codegen. Specify the path to your .js file in your codegen.yml config file:

codegen.yml
schema: my-schema.graphql
documents: './src/**/*.graphql'
generates:
  output.ts:
    - my-plugin.js

Now, run the @graphql-codegen/cli using graphql-codegen command, and it will create a file called output.ts with Hi!

Using the GraphQLSchema

The first argument of your plugin function is the GraphQLSchema.

Then, the code-generator will make sure to merge all GraphQLSchema's into a single, easy-to-use object that you can use to create your output.

You can find the fully-typed API of GraphQLSchema here.

So let's use a very basic method from GraphQLSchema, and return a list of all GraphQL types declared in the schema:

my-plugin.js
module.exports = {
  plugin(schema, documents, config, info) {
    const typesMap = schema.getTypeMap()
 
    return Object.keys(typesMap).join('\n')
  }
}

Using the documents

The second argument of your plugin method is an array of GraphQL documents. This array contains a list of { location: string, document: DocumentNode }.

The location field is the file's path, and DocumentNode is an object containing all GraphQL documents that have been found in that file.

You can find the fully-typed API of DocumentNode here.

Let's print a list of all documents files, and the name of operations in this file:

my-plugin.js
module.exports = {
  plugin(schema, documents, config, info) {
    return documents
      .map(doc => {
        const docsNames = doc.document.definitions.map(def => def.name.value)
 
        return `File ${doc.location} contains: ${docsNames.join(', ')}`
      })
      .join('\n')
  }
}

Add plugin configuration

The third argument of your function is config, and it includes an object with the configuration passed to your Plugin.

You can use it to tweak the behavior of your Plugin and allow developers to customize the output easily.

You can pass configuration to your plugin in the following this way:

codegen.yml
schema: my-schema.graphql
documents: './src/**/*.graphql'
generates:
  output.ts:
    - my-plugin.js:
        myConfig: 'some-value'

And then, you can use in your plugin:

my-plugin.js
module.exports = {
  plugin(schema, documents, config, info) {
    if (extname(info.outputFile) === '.graphql') {
      return 'baz'
    }
 
    return config.myConfig === 'some-value' ? 'foo' : 'bar'
  }
}

Packing your Plugin

To pack your Plugin as a package, create a simple package.json file and add the main field, pointing to your Plugin file.

Then, publish it to npm using npm publish and test it by installing the published package from npm, and use it in your YML config file:

codegen.yml
schema: my-schema.graphql
documents: './src/**/*.graphql'
generates:
  output.ts:
    - my-custom-plugin-package
💡

If you are using TypeScript to write your Plugin, don't forget to compile your .ts file using tsc and point main to the compiled file.