diff --git a/backend/internal/web/adapters/actions.go b/backend/internal/web/adapters/actions.go new file mode 100644 index 0000000..d14668e --- /dev/null +++ b/backend/internal/web/adapters/actions.go @@ -0,0 +1,50 @@ +package adapters + +import ( + "net/http" + + "github.com/hay-kot/homebox/backend/pkgs/server" +) + +// Action is a function that adapts a function to the server.Handler interface. +// It decodes the request body into a value of type T and passes it to the function f. +// The function f is expected to return a value of type Y and an error. +// +// Note: Action differs from Query in that it decodes the request body. +func Action[T any, Y any](f AdapterFunc[T, Y], ok int) server.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) error { + v, err := decode[T](r) + if err != nil { + return err + } + + res, err := f(r.Context(), v) + if err != nil { + return err + } + + return server.Respond(w, ok, res) + } +} + +// ActionID functions the same as Action, but it also decodes a UUID from the URL path. +func ActionID[T any, Y any](param string, f IDFunc[T, Y], ok int) server.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) error { + ID, err := routeUUID(r, param) + if err != nil { + return err + } + + v, err := decode[T](r) + if err != nil { + return err + } + + res, err := f(r.Context(), ID, v) + if err != nil { + return err + } + + return server.Respond(w, ok, res) + } +} diff --git a/backend/internal/web/adapters/adapters.go b/backend/internal/web/adapters/adapters.go index bd9e30c..316c836 100644 --- a/backend/internal/web/adapters/adapters.go +++ b/backend/internal/web/adapters/adapters.go @@ -3,93 +3,9 @@ package adapters import ( "context" - "net/http" "github.com/google/uuid" - "github.com/hay-kot/homebox/backend/pkgs/server" ) type AdapterFunc[T any, Y any] func(context.Context, T) (Y, error) type IDFunc[T any, Y any] func(context.Context, uuid.UUID, T) (Y, error) - -// Query is a server.Handler that decodes a query from the request and calls the provided function. -func Query[T any, Y any](f AdapterFunc[T, Y], ok int) server.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) error { - q, err := decodeQuery[T](r) - if err != nil { - return err - } - - res, err := f(r.Context(), q) - if err != nil { - return err - } - - return server.Respond(w, ok, res) - } -} - -// QueryID is a server.Handler that decodes a query and an ID from the request and calls the provided function. -func QueryID[T any, Y any](param string, f IDFunc[T, Y], ok int) server.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) error { - ID, err := routeUUID(r, param) - if err != nil { - return err - } - - q, err := decodeQuery[T](r) - if err != nil { - return err - } - - res, err := f(r.Context(), ID, q) - if err != nil { - return err - } - - return server.Respond(w, ok, res) - } -} - -// Action is a function that adapts a function to the server.Handler interface. -// It decodes the request body into a value of type T and passes it to the function f. -// The function f is expected to return a value of type Y and an error. -// -// Note: Action differs from Query in that it decodes the request body. -func Action[T any, Y any](f AdapterFunc[T, Y], ok int) server.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) error { - v, err := decode[T](r) - if err != nil { - return err - } - - res, err := f(r.Context(), v) - if err != nil { - return err - } - - return server.Respond(w, ok, res) - } -} - -// ActionID functions the same as Action, but it also decodes a UUID from the URL path. -func ActionID[T any, Y any](param string, f IDFunc[T, Y], ok int) server.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) error { - ID, err := routeUUID(r, param) - if err != nil { - return err - } - - v, err := decode[T](r) - if err != nil { - return err - } - - res, err := f(r.Context(), ID, v) - if err != nil { - return err - } - - return server.Respond(w, ok, res) - } -} diff --git a/backend/internal/web/adapters/command.go b/backend/internal/web/adapters/command.go new file mode 100644 index 0000000..d292d18 --- /dev/null +++ b/backend/internal/web/adapters/command.go @@ -0,0 +1,39 @@ +package adapters + +import ( + "context" + "net/http" + + "github.com/google/uuid" + "github.com/hay-kot/homebox/backend/pkgs/server" +) + +type CommandFunc[T any] func(context.Context) (T, error) +type CommandIDFunc[T any] func(context.Context, uuid.UUID) (T, error) + +func Command[T any](f CommandFunc[T], ok int) server.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) error { + res, err := f(r.Context()) + if err != nil { + return err + } + + return server.Respond(w, ok, res) + } +} + +func CommandID[T any](param string, f CommandIDFunc[T], ok int) server.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) error { + ID, err := routeUUID(r, param) + if err != nil { + return err + } + + res, err := f(r.Context(), ID) + if err != nil { + return err + } + + return server.Respond(w, ok, res) + } +} diff --git a/backend/internal/web/adapters/query.go b/backend/internal/web/adapters/query.go new file mode 100644 index 0000000..8d10d00 --- /dev/null +++ b/backend/internal/web/adapters/query.go @@ -0,0 +1,46 @@ +package adapters + +import ( + "net/http" + + "github.com/hay-kot/homebox/backend/pkgs/server" +) + +// Query is a server.Handler that decodes a query from the request and calls the provided function. +func Query[T any, Y any](f AdapterFunc[T, Y], ok int) server.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) error { + q, err := decodeQuery[T](r) + if err != nil { + return err + } + + res, err := f(r.Context(), q) + if err != nil { + return err + } + + return server.Respond(w, ok, res) + } +} + +// QueryID is a server.Handler that decodes a query and an ID from the request and calls the provided function. +func QueryID[T any, Y any](param string, f IDFunc[T, Y], ok int) server.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) error { + ID, err := routeUUID(r, param) + if err != nil { + return err + } + + q, err := decodeQuery[T](r) + if err != nil { + return err + } + + res, err := f(r.Context(), ID, q) + if err != nil { + return err + } + + return server.Respond(w, ok, res) + } +}