Files
ent/entc/gen/template/runtime.tmpl
2020-10-11 14:27:29 +03:00

195 lines
6.8 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.NumPolicy }}{{ $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 }}"
{{- /* Import external packages */}}
{{- template "import/types" $n }}
{{- end }}
"github.com/facebook/ent"
"github.com/facebook/ent/privacy"
)
// The init function reads all schema descriptors with runtime code
// (default values, validators, hooks and policies) and stitches it
// to their package variables.
func init() {
{{- range $n := $.Nodes }}
{{- $pkg := $n.Package }}
{{- $schema := base $.Config.Schema }}
{{- with $n.RuntimeMixin }}
{{ $pkg }}Mixin := {{ $schema }}.{{ $n.Name }}{}.Mixin()
{{- end }}
{{- with $policies := $n.PolicyPositions }}
{{- /* policies defined in schema and mixins. */}}
{{ $pkg }}.Policy = privacy.NewPolicies({{ range $idx := $n.MixedInPolicies }}{{ $pkg }}Mixin[{{ $idx }}],{{ end }}{{ $schema }}.{{ $n.Name }}{})
{{ $pkg }}.Hooks[0] = func(next ent.Mutator) ent.Mutator {
return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if err := {{ $pkg }}.Policy.EvalMutation(ctx, m); err != nil {
return nil, err
}
return next.Mutate(ctx, m)
})
}
{{- end }}
{{- with $hooks := $n.HookPositions }}
{{- /* Hooks defined in schema mixins. */}}
{{- with $idx := $n.MixedInHooks }}
{{- range $i := $idx }}
{{ print $pkg "MixinHooks" $i }} := {{ $pkg }}Mixin[{{ $i }}].Hooks()
{{- end }}
{{- end }}
{{- /* If there are hooks defined in the schema. */}}
{{- $schemaHooks := false }}{{ range $p := $hooks }}{{ if not $p.MixedIn }}{{ $schemaHooks = true }}{{ end }}{{ end }}
{{- if $schemaHooks }}
{{ print $pkg "Hooks" }} := {{ $schema }}.{{ $n.Name }}{}.Hooks()
{{- end }}
{{- range $i, $p := $hooks }}
{{- if $n.NumPolicy }}
{{ $i = add $i 1 }}
{{- end }}
{{- if $p.MixedIn }}
{{ print $pkg ".Hooks" }}[{{ $i }}] = {{ print $pkg "MixinHooks" $p.MixinIndex }}[{{ $p.Index }}]
{{- else }}
{{ print $pkg ".Hooks" }}[{{ $i }}] = {{ print $pkg "Hooks" }}[{{ $p.Index }}]
{{- end }}
{{- end }}
{{- end }}
{{- if or $n.HasDefault $n.HasValidators }}
{{- with $idx := $n.MixedInFields }}
{{- range $i := $idx }}
{{ print $pkg "MixinFields" $i }} := {{ $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 }}
// {{ $desc }} is the schema descriptor for {{ $f.Name }} field.
{{- if $f.Position.MixedIn }}
{{ $desc }} := {{ print $pkg "MixinFields" $f.Position.MixinIndex }}[{{ $f.Position.Index }}].Descriptor()
{{- else }}
{{ $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.
{{- $defaultType := print $f.Type.Type }}{{ if or $f.IsTime $f.IsUUID }}{{ $defaultType = print "func() " $f.Type }}{{ end }}
{{- if and $f.HasGoType (not (hasPrefix $defaultType "func")) }}
{{ $default }} = {{ $f.Type }}({{ $desc }}.Default.({{ $defaultType }}))
{{- else }}
{{ $default }} = {{ $desc }}.Default.({{ $defaultType }})
{{- end }}
{{- 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.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.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 }}