package builderimp import ( "time" "git.sendico.io/tech/sxchnge/shared/database/record" "git.sendico.io/tech/sxchnge/shared/database/repository/builder" "go.mongodb.org/mongo-driver/v2/bson" ) type patchBuilder struct { updates bson.D } func set(field builder.Field, value any) bson.E { return bson.E{Key: string(builder.Set), Value: bson.D{{Key: field.Build(), Value: value}}} } func (u *patchBuilder) Set(field builder.Field, value any) builder.Patch { u.updates = append(u.updates, set(field, value)) return u } func (u *patchBuilder) Inc(field builder.Field, value any) builder.Patch { u.updates = append(u.updates, bson.E{Key: string(builder.Inc), Value: bson.D{{Key: field.Build(), Value: value}}}) return u } func (u *patchBuilder) Unset(field builder.Field) builder.Patch { u.updates = append(u.updates, bson.E{Key: string(builder.Unset), Value: bson.D{{Key: field.Build(), Value: ""}}}) return u } func (u *patchBuilder) Rename(field builder.Field, newName string) builder.Patch { u.updates = append(u.updates, bson.E{Key: string(builder.Rename), Value: bson.D{{Key: field.Build(), Value: newName}}}) return u } func (u *patchBuilder) Push(field builder.Field, value any) builder.Patch { u.updates = append(u.updates, bson.E{Key: string(builder.Push), Value: bson.D{{Key: field.Build(), Value: value}}}) return u } func (u *patchBuilder) Pull(field builder.Field, value any) builder.Patch { u.updates = append(u.updates, bson.E{Key: string(builder.Pull), Value: bson.D{{Key: field.Build(), Value: value}}}) return u } func (u *patchBuilder) AddToSet(field builder.Field, value any) builder.Patch { u.updates = append(u.updates, bson.E{Key: string(builder.AddToSet), Value: bson.D{{Key: field.Build(), Value: value}}}) return u } func (u *patchBuilder) Build() bson.D { updates := append(bson.D{}, u.updates...) updates = append(updates, set(NewFieldImp(storable.UpdatedAtField), time.Now())) return mergePatchOperations(updates) } func NewPatchImp() builder.Patch { return &patchBuilder{updates: bson.D{}} } func mergePatchOperations(updates bson.D) bson.D { operators := make([]string, 0, len(updates)) merged := make(map[string]bson.D, len(updates)) for _, update := range updates { fields, ok := update.Value.(bson.D) if !ok { operators = appendMissingOperator(operators, update.Key) merged[update.Key] = append(merged[update.Key], bson.E{Key: update.Key, Value: update.Value}) continue } operators = appendMissingOperator(operators, update.Key) for _, field := range fields { merged[update.Key] = setPatchField(merged[update.Key], field) } } out := make(bson.D, 0, len(operators)) for _, operator := range operators { out = append(out, bson.E{Key: operator, Value: merged[operator]}) } return out } func appendMissingOperator(operators []string, operator string) []string { for _, existing := range operators { if existing == operator { return operators } } return append(operators, operator) } func setPatchField(fields bson.D, field bson.E) bson.D { for i := range fields { if fields[i].Key == field.Key { fields[i] = field return fields } } return append(fields, field) }