42 lines
1.1 KiB
Go
42 lines
1.1 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
|
|
"git.fabledsword.com/bvandeusen/minstrel/internal/apierror"
|
|
)
|
|
|
|
// resolveByID parses paramKey as a UUID, fetches the row via fetch, and
|
|
// returns the row. On invalid UUID, returns BadRequest. On pgx.ErrNoRows,
|
|
// returns NotFound with code "<notFoundCode>_not_found". On other fetch
|
|
// errors, returns Internal (caller is responsible for logging if needed).
|
|
//
|
|
// Generic over T because dbq getters return concrete dbq row types.
|
|
func resolveByID[T any](
|
|
r *http.Request,
|
|
paramKey string,
|
|
fetch func(context.Context, pgtype.UUID) (T, error),
|
|
notFoundCode string,
|
|
) (T, *apierror.Error) {
|
|
var zero T
|
|
raw := chi.URLParam(r, paramKey)
|
|
id, ok := parseUUID(raw)
|
|
if !ok {
|
|
return zero, apierror.BadRequest("bad_request", "invalid "+paramKey+" id")
|
|
}
|
|
row, err := fetch(r.Context(), id)
|
|
if err != nil {
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
return zero, apierror.NotFound(notFoundCode)
|
|
}
|
|
return zero, apierror.Internal(err)
|
|
}
|
|
return row, nil
|
|
}
|