{{/* 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. */}} {{/* gotype: entgo.io/ent/entc/gen.Graph */}} {{/* 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 }} "entgo.io/ent" "entgo.io/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() _ = {{ $pkg }}MixinFields{{ $i }} {{- 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 $f.DefaultFunc }}{{ $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.Type }}) error { {{- range $j, $n := xrange $f.Validators }} validators[{{ $j }}].(func({{ $f.Type.Type }}) error), {{- end }} } return func({{ $f.BuilderField }} {{ $f.Type.Type }}) error { for _, fn := range fns { if err := fn({{ $f.BuilderField }}); err != nil { return err } } return nil } }() {{- end }} {{- end }} {{- end }} {{- end }} {{- end }} } {{ end }}