| package entutils |
|
|
| import ( |
| "fmt" |
| "time" |
|
|
| "entgo.io/ent" |
| "entgo.io/ent/dialect" |
| "entgo.io/ent/dialect/entsql" |
| "entgo.io/ent/schema/field" |
| "entgo.io/ent/schema/index" |
| "entgo.io/ent/schema/mixin" |
| "github.com/oklog/ulid/v2" |
|
|
| "github.com/openmeterio/openmeter/pkg/clock" |
| "github.com/openmeterio/openmeter/pkg/convert" |
| "github.com/openmeterio/openmeter/pkg/models" |
| ) |
|
|
| |
| type UniqueResourceMixin struct { |
| mixin.Schema |
| } |
|
|
| func (UniqueResourceMixin) Fields() []ent.Field { |
| fields := ResourceMixin{}.Fields() |
| fields = append(fields, KeyMixin{}.Fields()...) |
|
|
| return fields |
| } |
|
|
| func (UniqueResourceMixin) Indexes() []ent.Index { |
| indexes := ResourceMixin{}.Indexes() |
|
|
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| indexes = append(indexes, index.Fields("namespace", "key", "deleted_at").Unique()) |
|
|
| return indexes |
| } |
|
|
| |
| type ResourceMixin struct { |
| mixin.Schema |
| MetadataDeprecatedReason string |
| } |
|
|
| func (m ResourceMixin) Fields() []ent.Field { |
| var fields []ent.Field |
| fields = append(fields, IDMixin{}.Fields()...) |
| fields = append(fields, NamespaceMixin{}.Fields()...) |
| fields = append(fields, MetadataMixin{DeprecatedReason: m.MetadataDeprecatedReason}.Fields()...) |
| fields = append(fields, TimeMixin{}.Fields()...) |
| fields = append(fields, |
| field.String("name"), |
| field.String("description").Optional().Nillable(), |
| ) |
|
|
| return fields |
| } |
|
|
| func (ResourceMixin) Indexes() []ent.Index { |
| var indexes []ent.Index |
| indexes = append(indexes, IDMixin{}.Indexes()...) |
| indexes = append(indexes, NamespaceMixin{}.Indexes()...) |
| indexes = append(indexes, MetadataMixin{}.Indexes()...) |
| indexes = append(indexes, TimeMixin{}.Indexes()...) |
| indexes = append(indexes, index.Fields("namespace", "id").Unique()) |
|
|
| return indexes |
| } |
|
|
| |
| type IDMixin struct { |
| mixin.Schema |
| } |
|
|
| |
| func (IDMixin) Fields() []ent.Field { |
| return []ent.Field{ |
| field.String("id"). |
| DefaultFunc(func() string { |
| return ulid.Make().String() |
| }). |
| Unique(). |
| Immutable(). |
| SchemaType(map[string]string{ |
| dialect.Postgres: "char(26)", |
| }), |
| } |
| } |
|
|
| func (IDMixin) Indexes() []ent.Index { |
| return []ent.Index{ |
| index.Fields("id").Unique(), |
| } |
| } |
|
|
| type IDMixinGetter interface { |
| GetID() string |
| } |
|
|
| type IDMixinCreator[T any] interface { |
| SetID(id string) T |
| } |
|
|
| |
| type KeyMixin struct { |
| mixin.Schema |
| } |
|
|
| |
| func (KeyMixin) Fields() []ent.Field { |
| return []ent.Field{ |
| field.String("key"). |
| NotEmpty(). |
| Immutable(), |
| } |
| } |
|
|
| |
| type NamespaceMixin struct { |
| mixin.Schema |
| } |
|
|
| |
| func (NamespaceMixin) Fields() []ent.Field { |
| return []ent.Field{ |
| field.String("namespace"). |
| NotEmpty(). |
| Immutable(), |
| } |
| } |
|
|
| func (NamespaceMixin) Indexes() []ent.Index { |
| return []ent.Index{ |
| index.Fields("namespace"), |
| } |
| } |
|
|
| type NamespaceMixinGetter interface { |
| GetNamespace() string |
| } |
|
|
| type NamespaceMixinCreator[T any] interface { |
| SetNamespace(namespace string) T |
| } |
|
|
| |
| type MetadataMixin struct { |
| mixin.Schema |
| DeprecatedReason string |
| } |
|
|
| |
| func (m MetadataMixin) Fields() []ent.Field { |
| metadata := field.JSON("metadata", map[string]string{}). |
| Optional(). |
| SchemaType(map[string]string{ |
| dialect.Postgres: "jsonb", |
| }) |
| if m.DeprecatedReason != "" { |
| metadata.Deprecated(m.DeprecatedReason) |
| } |
|
|
| return []ent.Field{metadata} |
| } |
|
|
| |
| type AnnotationsMixin struct { |
| mixin.Schema |
| DeprecatedReason string |
| } |
|
|
| |
| func (m AnnotationsMixin) Fields() []ent.Field { |
| annotations := field.JSON("annotations", models.Annotations{}). |
| Optional(). |
| SchemaType(map[string]string{ |
| dialect.Postgres: "jsonb", |
| }) |
| if m.DeprecatedReason != "" { |
| annotations.Deprecated(m.DeprecatedReason) |
| } |
|
|
| return []ent.Field{annotations} |
| } |
|
|
| func (AnnotationsMixin) Indexes() []ent.Index { |
| return []ent.Index{ |
| index.Fields("annotations"). |
| Annotations( |
| entsql.IndexTypes(map[string]string{ |
| dialect.Postgres: "GIN", |
| }), |
| ), |
| } |
| } |
|
|
| type AnnotationsMixinGetter interface { |
| GetAnnotations() models.Annotations |
| } |
|
|
| type AnnotationsMixinSetter[T any] interface { |
| SetAnnotations(annotations models.Annotations) T |
| } |
|
|
| |
| type TimeMixin struct { |
| mixin.Schema |
| } |
|
|
| |
| func (TimeMixin) Fields() []ent.Field { |
| return []ent.Field{ |
| field.Time("created_at"). |
| Default(truncatedNow). |
| Immutable(), |
| field.Time("updated_at"). |
| Default(truncatedNow). |
| UpdateDefault(truncatedNow), |
| field.Time("deleted_at"). |
| Optional(). |
| Nillable(), |
| } |
| } |
|
|
| type TimeMixinGetter interface { |
| GetCreatedAt() time.Time |
| GetUpdatedAt() time.Time |
| GetDeletedAt() *time.Time |
| } |
|
|
| type TimeMixinCreator[T any] interface { |
| SetCreatedAt(createdAt time.Time) T |
| SetUpdatedAt(updatedAt time.Time) T |
| SetNillableDeletedAt(deletedAt *time.Time) T |
| } |
|
|
| type TimeMixinUpdater[T any] interface { |
| SetUpdatedAt(updatedAt time.Time) T |
| SetNillableDeletedAt(deletedAt *time.Time) T |
| } |
|
|
| func MapTimeMixinFromDB[T TimeMixinGetter](dbEntity T) models.ManagedModel { |
| return models.ManagedModel{ |
| CreatedAt: dbEntity.GetCreatedAt().In(time.UTC), |
| UpdatedAt: dbEntity.GetUpdatedAt().In(time.UTC), |
| DeletedAt: convert.TimePtrIn(dbEntity.GetDeletedAt(), time.UTC), |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| func truncatedNow() time.Time { |
| |
| |
| return clock.Now().Truncate(time.Microsecond) |
| } |
|
|
| type CadencedMixin struct { |
| mixin.Schema |
| } |
|
|
| func (CadencedMixin) Fields() []ent.Field { |
| return []ent.Field{ |
| field.Time("active_from").Immutable(), |
| field.Time("active_to").Optional().Nillable(), |
| } |
| } |
|
|
| |
| type CustomerAddressMixin struct { |
| ent.Schema |
| FieldPrefix string |
| } |
|
|
| func (c CustomerAddressMixin) Fields() []ent.Field { |
| return []ent.Field{ |
| |
| field.String(fmt.Sprintf("%s_address_country", c.FieldPrefix)).GoType(models.CountryCode("")).MinLen(2).MaxLen(2).Optional().Nillable(), |
| field.String(fmt.Sprintf("%s_address_postal_code", c.FieldPrefix)).Optional().Nillable(), |
| field.String(fmt.Sprintf("%s_address_state", c.FieldPrefix)).Optional().Nillable(), |
| field.String(fmt.Sprintf("%s_address_city", c.FieldPrefix)).Optional().Nillable(), |
| field.String(fmt.Sprintf("%s_address_line1", c.FieldPrefix)).Optional().Nillable(), |
| field.String(fmt.Sprintf("%s_address_line2", c.FieldPrefix)).Optional().Nillable(), |
| field.String(fmt.Sprintf("%s_address_phone_number", c.FieldPrefix)).Optional().Nillable(), |
| } |
| } |
|
|