Skip to content

Commit

Permalink
Export default modelgen hooks (#2467)
Browse files Browse the repository at this point in the history
Co-authored-by: Roman A. Grigorovich <ragrigorov@mts.ru>
  • Loading branch information
atzedus and Roman A. Grigorovich authored Dec 13, 2022
1 parent 6b8c6ee commit da43147
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 20 deletions.
24 changes: 15 additions & 9 deletions docs/content/recipes/modelgen-hook.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Allowing mutation of generated models before rendering"
description: How to use a model mutation function to insert a ORM-specific tags onto struct fields.
linkTitle: "Modelgen hook"
menu: { main: { parent: 'recipes' } }
menu: { main: { parent: "recipes" } }
---

## BuildMutateHook
Expand All @@ -16,7 +16,7 @@ the generated data structure.
First of all, we need to create a function that will mutate the generated model.
Then we can attach the function to the plugin and use it like any other plugin.

``` go
```go
import (
"fmt"
"os"
Expand Down Expand Up @@ -64,8 +64,8 @@ This schema:

```graphql
type Object {
field1: String
field2: Int
field1: String
field2: Int
}
```

Expand All @@ -84,7 +84,7 @@ For more fine grained control over model generation, a graphql schema aware a Fi

The below recipe uses this feature to add validate tags to the generated model for use with `go-playground/validator` where the validate tags are defined in a constraint directive in the schema.

``` go
```go
import (
"fmt"
"github.com/vektah/gqlparser/v2/ast"
Expand All @@ -97,6 +97,11 @@ import (

// Defining mutation function
func constraintFieldHook(td *ast.Definition, fd *ast.FieldDefinition, f *modelgen.Field) (*modelgen.Field, error) {
// Call default hook to proceed standard directives like goField and goTag.
// You can omit it, if you don't need.
if f, err := modelgen.DefaultFieldMutateHook(td, fd, f); err != nil {
return f, err
}

c := fd.Directives.ForName("constraint")
if c != nil {
Expand Down Expand Up @@ -136,12 +141,12 @@ This schema:

```graphql
directive @constraint(
format: String
format: String
) on INPUT_FIELD_DEFINITION | FIELD_DEFINITION

input ObjectInput {
contactEmail: String @constraint(format: "email")
website: String @constraint(format: "uri")
contactEmail: String @constraint(format: "email")
website: String @constraint(format: "uri")
}
```

Expand All @@ -155,10 +160,11 @@ type ObjectInput struct {
```

If a constraint being used during generation should not be published during introspection, the directive should be listed with `skip_runtime:true` in gqlgen.yml

```yaml
directives:
constraint:
skip_runtime: true
```
The built-in directive `@goTag` is implemented using the FieldMutateHook. See: `plugin/modelgen/models.go` function `GoTagFieldHook`
The built-in directives `@goField` and `@goTag` is implemented using the FieldMutateHook. See: `plugin/modelgen/models.go` functions `GoFieldHook` and `GoTagFieldHook`
19 changes: 10 additions & 9 deletions plugin/modelgen/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ import (
//go:embed models.gotpl
var modelTemplate string

type BuildMutateHook = func(b *ModelBuild) *ModelBuild

type FieldMutateHook = func(td *ast.Definition, fd *ast.FieldDefinition, f *Field) (*Field, error)
type (
BuildMutateHook = func(b *ModelBuild) *ModelBuild
FieldMutateHook = func(td *ast.Definition, fd *ast.FieldDefinition, f *Field) (*Field, error)
)

// defaultFieldMutateHook is the default hook for the Plugin which applies the GoTagFieldHook.
func defaultFieldMutateHook(td *ast.Definition, fd *ast.FieldDefinition, f *Field) (*Field, error) {
// DefaultFieldMutateHook is the default hook for the Plugin which applies the GoFieldHook and GoTagFieldHook.
func DefaultFieldMutateHook(td *ast.Definition, fd *ast.FieldDefinition, f *Field) (*Field, error) {
var err error
f, err = GoFieldHook(td, fd, f)
if err != nil {
Expand All @@ -31,7 +32,8 @@ func defaultFieldMutateHook(td *ast.Definition, fd *ast.FieldDefinition, f *Fiel
return GoTagFieldHook(td, fd, f)
}

func defaultBuildMutateHook(b *ModelBuild) *ModelBuild {
// DefaultBuildMutateHook is the default hook for the Plugin which mutate ModelBuild.
func DefaultBuildMutateHook(b *ModelBuild) *ModelBuild {
return b
}

Expand Down Expand Up @@ -80,8 +82,8 @@ type EnumValue struct {

func New() plugin.Plugin {
return &Plugin{
MutateHook: defaultBuildMutateHook,
FieldHook: defaultFieldMutateHook,
MutateHook: DefaultBuildMutateHook,
FieldHook: DefaultFieldMutateHook,
}
}

Expand All @@ -97,7 +99,6 @@ func (m *Plugin) Name() string {
}

func (m *Plugin) MutateConfig(cfg *config.Config) error {

b := &ModelBuild{
PackageName: cfg.Model.Package,
}
Expand Down
4 changes: 2 additions & 2 deletions plugin/modelgen/models_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestModelGeneration(t *testing.T) {
require.NoError(t, cfg.Init())
p := Plugin{
MutateHook: mutateHook,
FieldHook: defaultFieldMutateHook,
FieldHook: DefaultFieldMutateHook,
}
require.NoError(t, p.MutateConfig(cfg))
require.NoError(t, goBuild(t, "./out/"))
Expand Down Expand Up @@ -279,7 +279,7 @@ func TestModelGenerationStructFieldPointers(t *testing.T) {
require.NoError(t, cfg.Init())
p := Plugin{
MutateHook: mutateHook,
FieldHook: defaultFieldMutateHook,
FieldHook: DefaultFieldMutateHook,
}
require.NoError(t, p.MutateConfig(cfg))

Expand Down

0 comments on commit da43147

Please sign in to comment.