/
edge.go
200 lines (171 loc) · 5.77 KB
/
edge.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
// 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.
package edge
import (
"reflect"
"entgo.io/ent/schema"
)
// A Descriptor for edge configuration.
type Descriptor struct {
Tag string // struct tag.
Type string // edge type.
Name string // edge name.
RefName string // ref name; inverse only.
Ref *Descriptor // edge reference; to/from of the same type.
Unique bool // unique edge.
Inverse bool // inverse edge.
Required bool // required on creation.
StorageKey *StorageKey // optional storage-key configuration.
Annotations []schema.Annotation // edge annotations.
}
// To defines an association edge between two vertices.
func To(name string, t interface{}) *assocBuilder {
return &assocBuilder{desc: &Descriptor{Name: name, Type: typ(t)}}
}
// From represents a reversed-edge between two vertices that has a back-reference to its source edge.
func From(name string, t interface{}) *inverseBuilder {
return &inverseBuilder{desc: &Descriptor{Name: name, Type: typ(t), Inverse: true}}
}
func typ(t interface{}) string {
if rt := reflect.TypeOf(t); rt.NumIn() > 0 {
return rt.In(0).Name()
}
return ""
}
// assocBuilder is the builder for assoc edges.
type assocBuilder struct {
desc *Descriptor
}
// Unique sets the edge type to be unique. Basically, it's limited the ent to be one of the two:
// one2one or one2many. one2one applied if the inverse-edge is also unique.
func (b *assocBuilder) Unique() *assocBuilder {
b.desc.Unique = true
return b
}
// Required indicates that this edge is a required field on creation.
// Unlike fields, edges are optional by default.
func (b *assocBuilder) Required() *assocBuilder {
b.desc.Required = true
return b
}
// StructTag sets the struct tag of the assoc edge.
func (b *assocBuilder) StructTag(s string) *assocBuilder {
b.desc.Tag = s
return b
}
// Assoc creates an inverse-edge with the same type.
func (b *assocBuilder) From(name string) *inverseBuilder {
return &inverseBuilder{desc: &Descriptor{Name: name, Type: b.desc.Type, Inverse: true, Ref: b.desc}}
}
// Comment used to put annotations on the schema.
func (b *assocBuilder) Comment(string) *assocBuilder {
return b
}
// StorageKey sets the storage key of the edge.
//
// edge.To("groups", Group.Type).
// StorageKey(edge.Table("user_groups"), edge.Columns("user_id", "group_id"))
//
func (b *assocBuilder) StorageKey(opts ...StorageOption) *assocBuilder {
if b.desc.StorageKey == nil {
b.desc.StorageKey = &StorageKey{}
}
for i := range opts {
opts[i](b.desc.StorageKey)
}
return b
}
// Annotations adds a list of annotations to the edge object to be used by
// codegen extensions.
//
// edge.To("pets", Pet.Type).
// Annotations(entgql.Config{
// FieldName: "Pets",
// })
//
func (b *assocBuilder) Annotations(annotations ...schema.Annotation) *assocBuilder {
b.desc.Annotations = append(b.desc.Annotations, annotations...)
return b
}
// Descriptor implements the ent.Descriptor interface.
func (b *assocBuilder) Descriptor() *Descriptor {
return b.desc
}
// inverseBuilder is the builder for inverse edges.
type inverseBuilder struct {
desc *Descriptor
}
// Ref sets the referenced-edge of this inverse edge.
func (b *inverseBuilder) Ref(ref string) *inverseBuilder {
b.desc.RefName = ref
return b
}
// Unique sets the edge type to be unique. Basically, it's limited the ent to be one of the two:
// one2one or one2many. one2one applied if the inverse-edge is also unique.
func (b *inverseBuilder) Unique() *inverseBuilder {
b.desc.Unique = true
return b
}
// Required indicates that this edge is a required field on creation.
// Unlike fields, edges are optional by default.
func (b *inverseBuilder) Required() *inverseBuilder {
b.desc.Required = true
return b
}
// StructTag sets the struct tag of the inverse edge.
func (b *inverseBuilder) StructTag(s string) *inverseBuilder {
b.desc.Tag = s
return b
}
// Comment used to put annotations on the schema.
func (b *inverseBuilder) Comment(string) *inverseBuilder {
return b
}
// Annotations adds a list of annotations to the edge object to be used by
// codegen extensions.
//
// edge.From("owner", User.Type).
// Ref("pets").
// Unique().
// Annotations(entgql.Config{
// FieldName: "Owner",
// })
//
func (b *inverseBuilder) Annotations(annotations ...schema.Annotation) *inverseBuilder {
b.desc.Annotations = append(b.desc.Annotations, annotations...)
return b
}
// Descriptor implements the ent.Descriptor interface.
func (b *inverseBuilder) Descriptor() *Descriptor {
return b.desc
}
// StorageKey holds the configuration for edge storage-key.
type StorageKey struct {
Table string // Table or label.
Columns []string // Foreign-key columns.
}
// StorageOption allows for setting the storage configuration using functional options.
type StorageOption func(*StorageKey)
// Table sets the table name option for M2M edges.
func Table(name string) StorageOption {
return func(key *StorageKey) {
key.Table = name
}
}
// Column sets the foreign-key column name option for O2O, O2M and M2O edges.
// Note that, for M2M edges (2 columns), use the edge.Columns option.
func Column(name string) StorageOption {
return func(key *StorageKey) {
key.Columns = []string{name}
}
}
// Columns sets the foreign-key column names option for M2M edges.
// The 1st column defines the name of the "To" edge, and the 2nd defines
// the name of the "From" edge (inverse edge).
// Note that, for O2O, O2M and M2O edges, use the edge.Column option.
func Columns(to, from string) StorageOption {
return func(key *StorageKey) {
key.Columns = []string{to, from}
}
}