package db import ( "context" "fmt" _ "github.com/lib/pq" "xorm.io/xorm" "todo-hetzner/app/internal/model" ) type Store struct { engine *xorm.Engine } func Open(databaseURL string) (*Store, error) { engine, err := xorm.NewEngine("postgres", databaseURL) if err != nil { return nil, fmt.Errorf("create database engine: %w", err) } engine.SetMaxOpenConns(10) engine.SetMaxIdleConns(5) if err := engine.Sync2(new(model.Todo)); err != nil { engine.Close() return nil, fmt.Errorf("migrate database: %w", err) } return &Store{engine: engine}, nil } func (s *Store) Ping(ctx context.Context) error { return s.engine.DB().PingContext(ctx) } func (s *Store) Close() error { return s.engine.Close() } func (s *Store) List(ctx context.Context) ([]model.Todo, error) { var todos []model.Todo err := s.engine.Context(ctx).Desc("created_at", "id").Find(&todos) return todos, err } func (s *Store) Create(ctx context.Context, title string) error { _, err := s.engine.Context(ctx).Insert(&model.Todo{Title: title}) return err } func (s *Store) Toggle(ctx context.Context, id int64) (bool, error) { var todo model.Todo found, err := s.engine.Context(ctx).ID(id).Get(&todo) if err != nil || !found { return found, err } todo.Completed = !todo.Completed _, err = s.engine.Context(ctx).ID(id).Cols("completed", "updated_at").Update(&todo) return true, err } func (s *Store) Delete(ctx context.Context, id int64) (bool, error) { affected, err := s.engine.Context(ctx).ID(id).Delete(new(model.Todo)) return affected > 0, err }