package api import ( "context" "errors" "github.com/jackc/pgx/v5" "git.dcrubro.com/dcrubro/hammy-backend/internal/db" ) // PgKeyStore adapts the sqlc-generated queries to the KeyStore interface. // The indirection earns its keep twice: the middleware is testable without a // database, and adding an unrelated column to api.keys does not ripple into the // auth package. type PgKeyStore struct { Q *db.Queries } func (s PgKeyStore) KeyByHash(ctx context.Context, hash []byte) (KeyRecord, error) { row, err := s.Q.KeyByHash(ctx, hash) if err != nil { // pgx returns ErrNoRows for an empty :one result. Translate it so the // middleware never has to know which driver is underneath. if errors.Is(err, pgx.ErrNoRows) { return KeyRecord{}, ErrKeyNotFound } return KeyRecord{}, err } rec := KeyRecord{ ID: row.ID, OwnerID: row.OwnerID, Scopes: row.Scopes, QuotaTier: row.QuotaTier, Status: row.Status, OwnerStatus: row.OwnerStatus, } // sqlc with emit_pointers_for_null_types gives *time.Time for a nullable // timestamptz. If your generated code uses pgtype.Timestamptz instead, // convert here rather than in the middleware. rec.ExpiresAt = row.ExpiresAt return rec, nil }