plugin

package module
v1.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 18, 2025 License: MIT Imports: 5 Imported by: 0

README

gqlscanner Plugin for gqlgen

A gqlgen plugin that automatically generates GraphQL schemas from Go structs with special annotations.

Installation

go get github.com/pablor21/gqlscanner/plugin

Important: How gqlgen Plugins Work

gqlgen plugins CANNOT be configured in gqlgen.yml. They must be registered programmatically in a custom code generation entrypoint.

If you try to add a plugins: section to gqlgen.yml, you'll get this error:

yaml: unmarshal errors: line X: field plugins not found in type config.Config

This is the correct way to use plugins with gqlgen.

Usage

1. Create a Custom Code Generation Entrypoint

Create a file named generate.go in your project root (same directory as gqlgen.yml):

//go:build ignore
// +build ignore

package main

import (
	"fmt"
	"os"

	"github.com/99designs/gqlgen/api"
	"github.com/99designs/gqlgen/codegen/config"
	"github.com/pablor21/gqlscanner/plugin"
)

func main() {
	cfg, err := config.LoadConfigFromDefaultLocations()
	if err != nil {
		fmt.Fprintln(os.Stderr, "failed to load config", err.Error())
		os.Exit(2)
	}

	// Create and configure the gqlscanner plugin
	p := plugin.New()
	p.Packages = []string{
		"./graph/models",  // Scan this directory for Go structs
	}

	// Generate code with the plugin
	err = api.Generate(cfg, api.AddPlugin(p))
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(3)
	}
}
2. Add Go Generate Directive

Add this comment to one of your Go files (e.g., create a tools.go file or add to server.go):

//go:generate go run generate.go

Example tools.go:

//go:build tools
// +build tools

package main

//go:generate go run generate.go

import (
	_ "github.com/99designs/gqlgen"
	_ "github.com/pablor21/gqlscanner/plugin"
)
3. Configure Your gqlgen.yml

Your gqlgen.yml contains standard gqlgen configuration (NO plugins section):

# Where to find the schema files that will be generated
schema:
  - graph/schema/*.graphql

# Generated code output
exec:
  filename: graph/generated.go
  package: graph

model:
  filename: graph/model/models_gen.go
  package: model

resolver:
  layout: follow-schema
  dir: graph
  package: graph
  filename_template: "{name}.resolvers.go"

# DO NOT add a plugins: section here - it won't work!
4. Run Code Generation
go generate ./...

Or directly:

go run generate.go

This will:

  1. Run your custom generate.go entrypoint
  2. gqlscanner plugin generates GraphQL schemas from your Go structs
  3. gqlgen continues with normal code generation

Configuration

All plugin configuration is done in your generate.go file:

Basic Configuration
p := plugin.New()

// Required: Packages to scan for Go structs with gql annotations
p.Packages = []string{
	"./graph/models",
	"./internal/domain",
}
Advanced Configuration

You can customize the scanner behavior through the plugin's internal config:

package main

import (
	"fmt"
	"os"

	"github.com/99designs/gqlgen/api"
	"github.com/99designs/gqlgen/codegen/config"
	"github.com/pablor21/gqlscanner/generator"
	"github.com/pablor21/gqlscanner/plugin"
)

func main() {
	cfg, err := config.LoadConfigFromDefaultLocations()
	if err != nil {
		fmt.Fprintln(os.Stderr, "failed to load config", err.Error())
		os.Exit(2)
	}

	// Create plugin with custom configuration
	genCfg := generator.NewConfig()
	
	// Generation strategy: single file or multiple files
	genCfg.GenStrategy = generator.GenStrategySingle // or GenStrategyMultiple
	
	// Output directory for generated schemas
	genCfg.Output = "graph/schema/generated"
	
	// Field name transformation
	genCfg.FieldCase = "camel" // camel, snake, pascal, original
	
	// Use json tags for field names
	genCfg.UseJSONTag = true
	
	// Generate @goModel and @goField directives
	genCfg.UseGQLGenDirectives = true
	
	// Strip prefixes/suffixes from type names
	genCfg.StripPrefix = []string{"DB", "Pg"}
	genCfg.StripSuffix = []string{"DTO", "Entity", "Model"}
	
	// Create plugin
	p := plugin.New()
	p.Packages = []string{"./graph/models"}
	
	// Note: Currently the plugin uses its default config
	// To use custom config, you may need to modify the plugin
	
	err = api.Generate(cfg, api.AddPlugin(p))
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(3)
	}
}
Configuration Options
Option Type Default Description
Packages []string [] Required. List of package paths to scan for Go structs

The plugin internally creates a generator.Config with these defaults:

  • GenStrategy: single (all types in one file)
  • Output: graph/schema/generated
  • FieldCase: camel
  • UseJSONTag: true
  • UseGQLGenDirectives: true

Examples

Example 1: Single Package
// generate.go
p := plugin.New()
p.Packages = []string{"./graph/models"}
Example 2: Multiple Packages
// generate.go
p := plugin.New()
p.Packages = []string{
	"./graph/models",
	"./internal/domain/entities",
	"./internal/domain/aggregates",
}
Example 3: Monorepo
// generate.go
p := plugin.New()
p.Packages = []string{
	"./services/user/models",
	"./services/product/models",
	"./pkg/common/types",
}

Workflow

Here's what happens when you run go generate ./...:

  1. generate.go executes

    • Loads gqlgen.yml configuration
    • Creates gqlscanner plugin instance
    • Configures packages to scan
  2. gqlscanner plugin runs (MutateConfig hook)

    • Scans specified packages for Go structs
    • Finds structs with gql annotations (gql.type, gql.input, etc.)
    • Generates .graphql schema files in the output directory
  3. gqlgen continues

    • Reads the generated schema files
    • Generates resolvers, models, and other code
    • Creates the final GraphQL server code

Annotating Your Structs

In your Go structs, use special comments to define GraphQL types:

package models

// gql.type
// User represents a user in the system
type User struct {
	ID        string    `json:"id"`        // Becomes: id: ID!
	Email     string    `json:"email"`     // Becomes: email: String!
	Name      string    `json:"name"`      // Becomes: name: String!
	CreatedAt time.Time `json:"createdAt"` // Becomes: createdAt: Time!
}

// gql.input
// CreateUserInput is the input for creating a user
type CreateUserInput struct {
	Email string `json:"email"` // email: String!
	Name  string `json:"name"`  // name: String!
}

For more details on annotations, see the main README.

Troubleshooting

Error: "field plugins not found in type config.Config"

This means you tried to add a plugins: section to gqlgen.yml. This doesn't work with gqlgen.

Solution: Remove the plugins: section from gqlgen.yml and configure the plugin in generate.go instead.

Plugin doesn't run

Make sure:

  1. You created generate.go with the correct code
  2. You added //go:generate go run generate.go to a .go file
  3. You're running go generate ./... or go run generate.go
No schemas generated

Check:

  1. p.Packages contains the correct paths to your struct files
  2. Your structs have the proper gql annotations (// gql.type, etc.)
  3. The output directory exists or can be created
Import errors in generate.go

The //go:build ignore comment prevents the file from being part of your normal build. The imports are resolved when you run go run generate.go.

Make sure you have installed the dependencies:

go get github.com/99designs/gqlgen
go get github.com/pablor21/gqlscanner/plugin
go mod tidy

Complete Example

See the examples/gqlgen-plugin directory for a complete working example.

Why This Approach?

gqlgen's architecture requires plugins to be registered programmatically because:

  1. Plugins can have complex configurations that don't fit in YAML
  2. Plugins may need to modify the gqlgen config before code generation
  3. This gives plugins full control over the generation process

While this requires an extra file (generate.go), it provides maximum flexibility and follows gqlgen's official plugin documentation.

Documentation

Overview

Package plugin provides a gqlgen plugin that automatically generates GraphQL schemas from Go structs with special annotations.

This plugin scans your Go code for structs and generates corresponding GraphQL types, inputs, and mutations based on struct tags and directives. It supports field name transformations, custom directives, and automatic input generation.

Installation

go get github.com/pablor21/gqlscanner/plugin

Usage

gqlgen plugins must be registered programmatically in a custom code generation entrypoint. Create a file named generate.go in your project root:

//go:build ignore

package main

import (
	"github.com/99designs/gqlgen/api"
	"github.com/99designs/gqlgen/codegen/config"
	"github.com/pablor21/gqlscanner/plugin"
)

func main() {
	cfg, _ := config.LoadConfigFromDefaultLocations()

	// Create and configure the plugin
	p := plugin.New()
	p.Packages = []string{"./graph/models"}

	// Generate with the plugin
	if err := api.Generate(cfg, api.AddPlugin(p)); err != nil {
		panic(err)
	}
}

Then run: go run generate.go

For detailed documentation and examples, see: https://github.com/pablor21/gqlscanner/tree/master/plugin

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Plugin

type Plugin struct {

	// Paths to scan for Go structs
	Packages []string `yaml:"packages"`
	// contains filtered or unexported fields
}

Plugin implements the gqlgen plugin interface

func New

func New() *Plugin

New creates a new instance of the plugin

func (*Plugin) MutateConfig

func (p *Plugin) MutateConfig(cfg *config.Config) error

MutateConfig is called before code generation This is where we generate the GraphQL schemas from Go structs

func (*Plugin) Name

func (p *Plugin) Name() string

Name returns the plugin name

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL