package items import ( "context" "database/sql" "errors" "github.com/uptrace/bun" ) // BunRepository is the Postgres implementation of Repository. It is the // only file in the package that speaks Bun/SQL. type BunRepository struct { db *bun.DB } // NewBunRepository wraps a *bun.DB opened by internal/database. func NewBunRepository(db *bun.DB) *BunRepository { return &BunRepository{db: db} } // List returns items newest-first, honoring the (already normalized) filter. // An empty result set encodes as [] on the wire, not null. func (r *BunRepository) List(ctx context.Context, f Filter) ([]Item, error) { var out []Item q := r.db.NewSelect().Model(&out) if f.Status != "" { q = q.Where("i.status = ?", f.Status) } if err := q. Order("i.created_at DESC", "i.id DESC"). Limit(f.Limit). Offset(f.Offset). Scan(ctx); err != nil { return nil, err } if out == nil { out = []Item{} } return out, nil } // Get fetches a single item by id, mapping missing rows to ErrNotFound. func (r *BunRepository) Get(ctx context.Context, id int64) (Item, error) { var item Item err := r.db.NewSelect().Model(&item).Where("i.id = ?", id).Scan(ctx) if errors.Is(err, sql.ErrNoRows) { return Item{}, ErrNotFound } return item, err } // Create inserts item and reads back the generated columns. func (r *BunRepository) Create(ctx context.Context, item *Item) error { return r.db.NewInsert().Model(item).Returning("*").Scan(ctx, item) } // Update persists item (matched by primary key); ErrNotFound when the row // is gone. func (r *BunRepository) Update(ctx context.Context, item *Item) error { res, err := r.db.NewUpdate().Model(item).WherePK().Exec(ctx) if err != nil { return err } if n, _ := res.RowsAffected(); n == 0 { return ErrNotFound } return nil } // Delete removes an item by id; ErrNotFound when the row is gone. func (r *BunRepository) Delete(ctx context.Context, id int64) error { res, err := r.db.NewDelete().Model((*Item)(nil)).Where("i.id = ?", id).Exec(ctx) if err != nil { return err } if n, _ := res.RowsAffected(); n == 0 { return ErrNotFound } return nil }