Files
ent/entc/gen/template/runtime.tmpl
2020-04-18 12:28:50 +03:00

171 lines
5.7 KiB
Cheetah

{{/*
Copyright 2019-present Facebook Inc. All rights reserved.
This source code is licensed under the Apache 2.0 license found
in the LICENSE file in the root directory of this source tree.
*/}}
{{/*
The runtime template generates the schema-stitching logic and holds the
module version that was used to generate the assets.
It has 2 formats. A "runtime" package that should be empty-imported in the
main package for schemas with hooks or policies (potential cyclic-import).
The second format is generated under the "ent" package, and empty-import is
not necessary (no option for cyclic-import). The second format used to keep
backwards-compatibility with previous versions of ent.
*/}}
{{ define "runtime/ent" }}
{{ template "runtime" $ }}
{{ end }}
{{ define "runtime/pkg" }}
{{ with extend $ "Package" "runtime" }}
{{ template "runtime" . }}
{{ end }}
{{ $module := $.ModuleInfo }}
{{ if or $module.Version $module.Sum }}
const (
{{- with $module.Version }}
Version = "{{ . }}" // Version of ent codegen.
{{- end }}
{{- with $module.Sum }}
Sum = "{{ . }}" // Sum of ent codegen.
{{- end }}
)
{{ end }}
{{ end }}
{{ define "runtime" }}
{{ template "header" . }}
{{ $hooks := 0 }}
{{ range $n := $.Nodes }}
{{ $numHooks := $n.NumHooks }}{{ if $n.HasPolicy }}{{ $numHooks = add $numHooks 1 }}{{ end }}
{{ $hooks = add $hooks $numHooks }}
{{ end }}
{{ $rtpkg := false }}{{ if hasField $ "Scope" }}{{ $rtpkg = eq $.Scope.Package "runtime" }}{{ end }}
{{ if $rtpkg }} {{/* 1st format - runtime/runtime.go */}}
{{ if $hooks }}
{{ template "runtime/register" $ }}
{{ else }}
// The schema-stitching logic is generated in {{ $.Config.Package }}/runtime.go
{{ end }}
{{ else }}{{/* 2nd format - ent/runtime.go */}}
{{ if not $hooks }}
{{ template "runtime/register" $ }}
{{ else }}
// The schema-stitching logic is generated in {{ $.Config.Package }}/runtime/runtime.go
{{ end }}
{{ end }}
{{ end }}
{{/* register schema handlers to type packages */}}
{{ define "runtime/register" }}
import (
{{- with $.Config.Schema }}
"{{ . }}"
{{- end }}
{{- range $n := $.Nodes }}
"{{ $.Config.Package }}/{{ $n.Package }}"
{{- end }}
"github.com/facebookincubator/ent"
)
// The init function reads all schema descriptors with runtime
// code (default values, validators or hooks) and stitches it
// to their package variables.
func init() {
{{- range $n := $.Nodes }}
{{- $pkg := $n.Package }}
{{- $schema := base $.Config.Schema }}
{{- if $n.HasPolicy }}
{{ print $pkg ".Policy" }} = {{ $schema }}.{{ $n.Name }}{}.Policy()
{{ print $pkg ".Hooks" }}[0] = func(next ent.Mutator) ent.Mutator {
return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if err := {{ print $pkg ".Policy" }}.EvalMutation(ctx, m); err != nil {
return nil, err
}
return next.Mutate(ctx, m)
})
}
{{- end }}
{{- if $n.NumHooks }}
{{ print $pkg "Hooks" }} := {{ $schema }}.{{ $n.Name }}{}.Hooks()
for i, h := range {{ print $pkg "Hooks" }} {
{{ print $pkg ".Hooks" }}[i{{ if $n.HasPolicy }}+1{{ end }}] = h
}
{{- end }}
{{- if or $n.HasDefault $n.HasValidators }}
{{- with $n.MixedInWithDefaultOrValidator }}
{{ $pkg }}Mixin := {{ $schema }}.{{ $n.Name }}{}.Mixin()
{{ $pkg }}MixinFields := [...][]ent.Field{
{{- range $i, $_ := xrange $n.NumMixin }}
{{ $pkg }}Mixin[{{ $i }}].Fields(),
{{- end }}
}
{{- end }}
{{- $fields := $n.Fields }}{{ if $n.ID.UserDefined }}{{ $fields = append $fields $n.ID }}{{ end }}
{{- with $fields }}
{{ $pkg }}Fields := {{ $schema }}.{{ $n.Name }}{}.Fields()
_ = {{ $pkg }}Fields
{{- end }}
{{- range $i, $f := $fields }}
{{- $desc := print $pkg "Desc" $f.StructField }}
{{- /* enum default values handled near their declarations (in type package). */}}
{{- if or (and $f.Default (not $f.IsEnum)) $f.UpdateDefault $f.Validators }}
{{- if $f.Position.MixedIn }}
// {{ $desc }} is the schema descriptor for {{ $f.Name }} field.
{{ $desc }} := {{ $pkg }}MixinFields[{{ $f.Position.MixinIndex }}][{{ $f.Position.Index }}].Descriptor()
{{- else }}
// {{ $desc }} is the schema descriptor for {{ $f.Name }} field.
{{ $desc }} := {{ $pkg }}Fields[{{ $f.Position.Index }}].Descriptor()
{{- end }}
{{- end }}
{{- if and $f.Default (not $f.IsEnum) }}
{{- $default := print $pkg "." $f.DefaultName }}
// {{ $default }} holds the default value on creation for the {{ $f.Name }} field.
{{ $default }} = {{ $desc }}.Default.({{ if or $f.IsTime $f.IsUUID }}func() {{ end }}{{ $f.Type }})
{{- end }}
{{- if $f.UpdateDefault }}
{{- $default := print $pkg "." $f.UpdateDefaultName }}
// {{ $default }} holds the default value on update for the {{ $f.Name }} field.
{{ $default }} = {{ $desc }}.UpdateDefault.({{ if $f.IsTime }}func() {{ end }}{{ $f.Type }})
{{- end }}
{{- with $f.Validators }}
{{- $name := print $pkg "." $f.Validator }}
{{- $type := printf "func (%s) error" $f.Type }}
// {{ $name }} is a validator for the "{{ $f.Name }}" field. It is called by the builders before save.
{{- if eq $f.Validators 1 }}
{{ $name }} = {{ $desc }}.Validators[0].({{ $type }})
{{- else }}
{{ $name }} = func() {{ $type }} {
validators := {{ $desc }}.Validators
fns := [...]func({{ $f.Type }}) error {
{{- range $j, $n := xrange $f.Validators }}
validators[{{ $j }}].(func({{ $f.Type }}) error),
{{- end }}
}
return func({{ $f.BuilderField }} {{ $f.Type }}) error {
for _, fn := range fns {
if err := fn({{ $f.BuilderField }}); err != nil {
return err
}
}
return nil
}
}()
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
}
{{ end }}