package localmixin import ( "context" "fmt" "time" "entgo.io/ent" "entgo.io/ent/dialect/entsql" "entgo.io/ent/dialect/sql" "entgo.io/ent/schema/field" "entgo.io/ent/schema/mixin" gen "wechat-api/ent" "wechat-api/ent/hook" "wechat-api/ent/intercept" ) // SoftDeleteMixin implements the soft delete pattern for schemas. type SoftDeleteMixin struct { mixin.Schema } // Fields of the SoftDeleteMixin. func (SoftDeleteMixin) Fields() []ent.Field { return []ent.Field{ field.Time("deleted_at"). Optional(). Comment("Delete Time | 删除日期"). Annotations(entsql.WithComments(true)), } } type softDeleteKey struct{} // SkipSoftDelete returns a new context that skips the soft-delete interceptor/mutators. func SkipSoftDelete(parent context.Context) context.Context { return context.WithValue(parent, softDeleteKey{}, true) } // Interceptors of the SoftDeleteMixin. func (d SoftDeleteMixin) Interceptors() []gen.Interceptor { return []gen.Interceptor{ intercept.TraverseFunc(func(ctx context.Context, q intercept.Query) error { // Skip soft-delete, means include soft-deleted entities. if skip, _ := ctx.Value(softDeleteKey{}).(bool); skip { return nil } d.P(q) return nil }), } } // Hooks of the SoftDeleteMixin. func (d SoftDeleteMixin) Hooks() []gen.Hook { return []gen.Hook{ hook.On( func(next gen.Mutator) gen.Mutator { return gen.MutateFunc(func(ctx context.Context, m gen.Mutation) (gen.Value, error) { // Skip soft-delete, means delete the entity permanently. if skip, _ := ctx.Value(softDeleteKey{}).(bool); skip { return next.Mutate(ctx, m) } mx, ok := m.(interface { SetOp(gen.Op) Client() *gen.Client SetDeletedAt(time.Time) WhereP(...func(*sql.Selector)) }) if !ok { return nil, fmt.Errorf("unexpected mutation type %T", m) } d.P(mx) mx.SetOp(gen.OpUpdate) mx.SetDeletedAt(time.Now()) return mx.Client().Mutate(ctx, m) }) }, gen.OpDeleteOne|gen.OpDelete, ), } } // P adds a storage-level predicate to the queries and mutations. func (d SoftDeleteMixin) P(w interface{ WhereP(...func(*sql.Selector)) }) { w.WhereP( sql.FieldIsNull(d.Fields()[0].Descriptor().Name), ) }