External Templates

    stringer.tmpl - This template example will be written in a file named: ent/stringer.go.

    debug.tmpl - This template example will be written in a file named: ent/debug.go.

    1. {{ define "debug" }}
    2. {{/* A template that adds the functionality for running each client <T> in debug mode */}}
    3. {{/* Add the base header for the generated file */}}
    4. {{ $pkg := base $.Config.Package }}
    5. {{ template "header" $ }}
    6. {{/* Loop over all nodes and add option the "Debug" method */}}
    7. {{ range $n := $.Nodes }}
    8. {{ $client := print $n.Name "Client" }}
    9. func (c *{{ $client }}) Debug() *{{ $client }} {
    10. if c.debug {
    11. return c
    12. }
    13. cfg := config{driver: dialect.Debug(c.driver, c.log), log: c.log, debug: true, hooks: c.hooks}
    14. return &{{ $client }}{config: cfg}
    15. }
    16. {{ end }}
    17. {{ end }}

    In order to override an existing template, use its name. For example:

    1. {{/* A template for adding additional fields to specific types. */}}
    2. {{ define "model/fields/additional" }}
    3. {{- /* Add static fields to the "Card" entity. */}}
    4. {{- if eq $.Name "Card" }}
    5. // StaticField defined by templates.
    6. StaticField string `json:"static_field,omitempty"`
    7. {{- end }}
    8. {{ end }}

    As mentioned above, ent writes each template’s execution output to a file named the same as the template. For example, the output from a template defined as {{ define "stringer" }} will be written to a file named ent/stringer.go.

    1. {{ define "helper/.+" }} for global helper templates. For example:
    1. {{ define "helper/foo" }}
    2. {{/* Logic goes here. */}}
    3. {{ define "helper/bar/baz" }}
    4. {{/* Logic goes here. */}}
    5. {{ end }}
    1. {{ define "<root-template>/helper/.+" }} for local helper templates. A template is considered as “root” if its execution output is written to a file. For example:

    Annotations

    Schema annotations allow attaching metadata to fields and edges and inject them to external templates.
    An annotation must be a Go type that is serializable to JSON raw value (e.g. struct, map or slice) and implement the interface.

    Here’s an example of an annotation and its usage in schema and template:

    1. An annotation definition:
    1. package entgql
    2. // Annotation annotates fields with metadata for templates.
    3. type Annotation struct {
    4. // OrderField is the ordering field as defined in graphql schema.
    5. OrderField string
    6. }
    7. // Name implements ent.Annotation interface.
    8. func (Annotation) Name() string {
    9. return "EntGQL"
    10. }
    1. Annotation usage in ent/schema:
    1. // User schema.
    2. type User struct {
    3. ent.Schema
    4. }
    5. // Fields of the user.
    6. func (User) Fields() []ent.Field {
    7. return []ent.Field{
    8. field.Time("creation_date").
    9. Annotations(entgql.Annotation{
    10. OrderField: "CREATED_AT",
    11. }),
    12. }
    13. }
    1. Annotation usage in external templates:
    1. {{ range $node := $.Nodes }}
    2. {{ range $f := $node.Fields }}
    3. {{/* Get the annotation by its name. See: Annotation.Name */}}
    4. {{ $orderField := $annotation.OrderField }}
    5. {{ end }}
    6. {{ end }}
    7. {{ end }}

    Global annotation is a type of annotation that is injected into the gen.Config object and can be accessed globally in all templates. For example, an annotation that holds a config file information (e.g. gqlgen.yml or swagger.yml) add can accessed in all templates:

    1. An annotation definition:
    1. Annotation usage in ent/entc.go:
    1. func main() {
    2. cfg, err := config.LoadConfig("<path to gqlgen.yml>")
    3. if err != nil {
    4. log.Fatalf("loading gqlgen config: %v", err)
    5. }
    6. opts := []entc.Option{
    7. entc.TemplateDir("./template"),
    8. entc.Annotations(gqlconfig.Annotation{Config: cfg}),
    9. }
    10. err = entc.Generate("./schema", &gen.Config{
    11. Templates: entgql.AllTemplates,
    12. }, opts...)
    13. if err != nil {
    14. log.Fatalf("running ent codegen: %v", err)
    15. }
    16. }
    1. Annotation usage in external templates:
    1. {{- with $.Annotations.GQL.Config.StructTag }}
    2. {{/* Access the GQL configuration on *gen.Graph */}}
    3. {{- end }}
    4. {{ range $node := $.Nodes }}
    5. {{- with $node.Config.Annotations.GQL.Config.StructTag }}
    6. {{/* Access the GQL configuration on *gen.Type */}}
    7. {{- end }}
    8. {{ end }}

    Examples

    • A custom template for implementing the Node API for GraphQL - .

    Templates are executed on either a specific node type, or the entire schema graph. For API documentation, see the GoDoc.

    AutoCompletion

    JetBrains users can add the following template annotation to enable the autocompletion in their templates:

    1. {{/* The line below tells Intellij/GoLand to enable the autocompletion based on the *gen.Graph type. */}}
    2. {{/* gotype: entgo.io/ent/entc/gen.Graph */}}
    3. {{ define "template" }}
    4. {{ end }}

    See it in action: