diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index ecd12b69..a8e00c37 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -10,7 +10,6 @@ on: pull_request: branches: - "master" - - "*" workflow_dispatch: inputs: ref: diff --git a/.golangci.yaml b/.golangci.yaml index 3ed1324c..52eb3148 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -115,3 +115,4 @@ formatters: - Default - Prefix(github.com/riverqueue) - Prefix(riverqueue.com/riverpro) + - Prefix(riverqueue.com/riverui) diff --git a/CHANGELOG.md b/CHANGELOG.md index 808b8850..5b30c79d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Breaking change:** River UI has been split into two modules and two executables: `riverui` for OSS-only functionality, and `riverproui` which adds Pro-specific functionality through dependencies on `riverqueue.com/riverpro`. This change makes it far easier to continue extending the UI for everybody but especially for Pro-specific feature. As part of this, the `Server` and `ServerOpts` types were also renamed to - `Handler` and `HandlerOpts` respectievly. Users who embed `riverui` into + `Handler` and `HandlerOpts` respectively. Users who embed `riverui` into their Go app as a handler will need to update their `riverui.NewServer` initialization to `riverui.NewHandler` and to provide an `Endpoints` option in `riverui.HandlerOpts`, using `riverui.NewEndpoints(client, nil)` for the OSS diff --git a/Dockerfile b/Dockerfile index bcdfd121..f7ccdd4d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,6 +23,8 @@ COPY *.go internal docs/README.md LICENSE ./ COPY cmd/ cmd/ COPY internal/ internal/ COPY public/ public/ +COPY uiendpoints/ uiendpoints/ + COPY --from=build-ui /app/dist ./dist RUN go build -trimpath -ldflags="-w -s -buildid=" -o /bin/riverui ./cmd/riverui diff --git a/Dockerfile.pro b/Dockerfile.pro index 618cc5a7..f9965c29 100644 --- a/Dockerfile.pro +++ b/Dockerfile.pro @@ -32,7 +32,10 @@ COPY *.go internal docs/README.md LICENSE ./ COPY cmd/ cmd/ COPY internal/ internal/ COPY public/ public/ +COPY uiendpoints/ uiendpoints/ + COPY riverproui/ riverproui/ + COPY --from=build-ui /app/dist ./dist # Build the riverproui binary diff --git a/cmd/riverui/main.go b/cmd/riverui/main.go index 53fd4001..63e9deca 100644 --- a/cmd/riverui/main.go +++ b/cmd/riverui/main.go @@ -3,12 +3,13 @@ package main import ( "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" - "riverqueue.com/riverui" - "riverqueue.com/riverui/internal/apibundle" - "riverqueue.com/riverui/internal/riveruicmd" "github.com/riverqueue/river" "github.com/riverqueue/river/riverdriver/riverpgxv5" + + "riverqueue.com/riverui" + "riverqueue.com/riverui/internal/riveruicmd" + "riverqueue.com/riverui/uiendpoints" ) func main() { @@ -16,7 +17,7 @@ func main() { func(dbPool *pgxpool.Pool) (*river.Client[pgx.Tx], error) { return river.NewClient(riverpgxv5.New(dbPool), &river.Config{}) }, - func(client *river.Client[pgx.Tx]) apibundle.EndpointBundle { + func(client *river.Client[pgx.Tx]) uiendpoints.Bundle { return riverui.NewEndpoints(client, nil) }, ) diff --git a/example_test.go b/example_test.go index 1b5cfc06..680526db 100644 --- a/example_test.go +++ b/example_test.go @@ -11,11 +11,12 @@ import ( "strings" "github.com/jackc/pgx/v5/pgxpool" - "riverqueue.com/riverui" "github.com/riverqueue/river" "github.com/riverqueue/river/riverdriver/riverpgxv5" "github.com/riverqueue/river/rivershared/util/slogutil" + + "riverqueue.com/riverui" ) // ExampleNewHandler demonstrates how to create a River UI handler, diff --git a/handler.go b/handler.go index 9eae3bd8..ccf8ea84 100644 --- a/handler.go +++ b/handler.go @@ -16,8 +16,6 @@ import ( "path/filepath" "strings" - "riverqueue.com/riverui/internal/apibundle" - "github.com/riverqueue/apiframe/apiendpoint" "github.com/riverqueue/apiframe/apimiddleware" "github.com/riverqueue/apiframe/apitype" @@ -25,12 +23,16 @@ import ( "github.com/riverqueue/river/riverdriver" "github.com/riverqueue/river/rivershared/baseservice" "github.com/riverqueue/river/rivershared/startstop" + + "riverqueue.com/riverui/internal/apibundle" + "riverqueue.com/riverui/uiendpoints" ) type endpointsExtensions interface { Extensions() map[string]bool } +// EndpointsOpts are the options for creating a new Endpoints bundle. type EndpointsOpts[TTx any] struct { // Tx is an optional transaction to wrap all database operations. It's mainly // used for testing. @@ -38,12 +40,19 @@ type EndpointsOpts[TTx any] struct { } type endpoints[TTx any] struct { - bundleOpts *apibundle.EndpointBundleOpts + bundleOpts *uiendpoints.BundleOpts client *river.Client[TTx] opts *EndpointsOpts[TTx] } -func NewEndpoints[TTx any](client *river.Client[TTx], opts *EndpointsOpts[TTx]) apibundle.EndpointBundle { +// NewEndpoints creates a new Endpoints bundle, which is a collection of API +// endpoints for a Handler. Endpoints must be provided to the Handler via the +// `Endpoints` option of `HandlerOpts`. +// +// This constructor returns the open source riverui bundle, whereas +// `riverproui.NewEndpoints` returns the Pro-specific bundle with Pro APIs and +// features enabled. +func NewEndpoints[TTx any](client *river.Client[TTx], opts *EndpointsOpts[TTx]) uiendpoints.Bundle { if opts == nil { opts = &EndpointsOpts[TTx]{} } @@ -53,7 +62,7 @@ func NewEndpoints[TTx any](client *river.Client[TTx], opts *EndpointsOpts[TTx]) } } -func (e *endpoints[TTx]) Configure(bundleOpts *apibundle.EndpointBundleOpts) { +func (e *endpoints[TTx]) Configure(bundleOpts *uiendpoints.BundleOpts) { e.bundleOpts = bundleOpts } @@ -104,7 +113,7 @@ func (e *endpoints[TTx]) MountEndpoints(archetype *baseservice.Archetype, logger type HandlerOpts struct { // DevMode is whether the server is running in development mode. DevMode bool - Endpoints apibundle.EndpointBundle + Endpoints uiendpoints.Bundle JobListHideArgsByDefault bool // LiveFS is whether to use the live filesystem for the frontend. LiveFS bool @@ -166,7 +175,7 @@ func NewHandler(opts *HandlerOpts) (*Handler, error) { return nil, err } - opts.Endpoints.Configure(&apibundle.EndpointBundleOpts{ + opts.Endpoints.Configure(&uiendpoints.BundleOpts{ JobListHideArgsByDefault: opts.JobListHideArgsByDefault, }) diff --git a/handler_api_endpoint.go b/handler_api_endpoint.go index 86997981..ef2c0544 100644 --- a/handler_api_endpoint.go +++ b/handler_api_endpoint.go @@ -10,9 +10,6 @@ import ( "strconv" "time" - "riverqueue.com/riverui/internal/apibundle" - "riverqueue.com/riverui/internal/querycacher" - "github.com/riverqueue/apiframe/apiendpoint" "github.com/riverqueue/apiframe/apierror" "github.com/riverqueue/apiframe/apitype" @@ -23,6 +20,9 @@ import ( "github.com/riverqueue/river/rivershared/util/ptrutil" "github.com/riverqueue/river/rivershared/util/sliceutil" "github.com/riverqueue/river/rivertype" + + "riverqueue.com/riverui/internal/apibundle" + "riverqueue.com/riverui/internal/querycacher" ) type listResponse[T any] struct { diff --git a/handler_api_endpoint_test.go b/handler_api_endpoint_test.go index bf78535d..28d62612 100644 --- a/handler_api_endpoint_test.go +++ b/handler_api_endpoint_test.go @@ -8,9 +8,6 @@ import ( "github.com/jackc/pgx/v5" "github.com/stretchr/testify/require" - "riverqueue.com/riverui/internal/apibundle" - "riverqueue.com/riverui/internal/riverinternaltest" - "riverqueue.com/riverui/internal/riverinternaltest/testfactory" "github.com/riverqueue/apiframe/apiendpoint" "github.com/riverqueue/apiframe/apierror" @@ -22,6 +19,10 @@ import ( "github.com/riverqueue/river/rivershared/startstop" "github.com/riverqueue/river/rivershared/util/ptrutil" "github.com/riverqueue/river/rivertype" + + "riverqueue.com/riverui/internal/apibundle" + "riverqueue.com/riverui/internal/riverinternaltest" + "riverqueue.com/riverui/internal/riverinternaltest/testfactory" ) type setupEndpointTestBundle struct { diff --git a/handler_test.go b/handler_test.go index fe4b209e..80e95b8f 100644 --- a/handler_test.go +++ b/handler_test.go @@ -9,14 +9,15 @@ import ( "github.com/jackc/pgx/v5" "github.com/stretchr/testify/require" - "riverqueue.com/riverui/internal/apibundle" - "riverqueue.com/riverui/internal/handlertest" - "riverqueue.com/riverui/internal/riverinternaltest" - "riverqueue.com/riverui/internal/riverinternaltest/testfactory" "github.com/riverqueue/apiframe/apitype" "github.com/riverqueue/river" "github.com/riverqueue/river/riverdriver" + + "riverqueue.com/riverui/internal/handlertest" + "riverqueue.com/riverui/internal/riverinternaltest" + "riverqueue.com/riverui/internal/riverinternaltest/testfactory" + "riverqueue.com/riverui/uiendpoints" ) func TestNewHandlerIntegration(t *testing.T) { @@ -24,13 +25,13 @@ func TestNewHandlerIntegration(t *testing.T) { createClient := insertOnlyClient - createBundle := func(client *river.Client[pgx.Tx], tx pgx.Tx) apibundle.EndpointBundle { + createBundle := func(client *river.Client[pgx.Tx], tx pgx.Tx) uiendpoints.Bundle { return NewEndpoints(client, &EndpointsOpts[pgx.Tx]{ Tx: &tx, }) } - createHandler := func(t *testing.T, bundle apibundle.EndpointBundle) http.Handler { + createHandler := func(t *testing.T, bundle uiendpoints.Bundle) http.Handler { t.Helper() logger := riverinternaltest.Logger(t) diff --git a/internal/apibundle/api_bundle.go b/internal/apibundle/api_bundle.go index 361f8cd4..e90127df 100644 --- a/internal/apibundle/api_bundle.go +++ b/internal/apibundle/api_bundle.go @@ -2,9 +2,7 @@ package apibundle import ( "log/slog" - "net/http" - "github.com/riverqueue/apiframe/apiendpoint" "github.com/riverqueue/river" "github.com/riverqueue/river/riverdriver" "github.com/riverqueue/river/rivershared/baseservice" @@ -20,13 +18,3 @@ type APIBundle[TTx any] struct { JobListHideArgsByDefault bool Logger *slog.Logger } - -type EndpointBundleOpts struct { - JobListHideArgsByDefault bool -} - -type EndpointBundle interface { - Configure(bundleOpts *EndpointBundleOpts) - MountEndpoints(archetype *baseservice.Archetype, logger *slog.Logger, mux *http.ServeMux, mountOpts *apiendpoint.MountOpts, extensions map[string]bool) []apiendpoint.EndpointInterface - Validate() error -} diff --git a/internal/handlertest/handlertest.go b/internal/handlertest/handlertest.go index 63f38e64..5fcad43d 100644 --- a/internal/handlertest/handlertest.go +++ b/internal/handlertest/handlertest.go @@ -11,15 +11,16 @@ import ( "github.com/jackc/pgx/v5" "github.com/stretchr/testify/require" - "riverqueue.com/riverui/internal/apibundle" - "riverqueue.com/riverui/internal/riverinternaltest" "github.com/riverqueue/river/riverdriver" + + "riverqueue.com/riverui/internal/riverinternaltest" + "riverqueue.com/riverui/uiendpoints" ) type APICallFunc = func(t *testing.T, testCaseName, method, path string, payload []byte) -func RunIntegrationTest[TClient any](t *testing.T, createClient func(t *testing.T, logger *slog.Logger) (TClient, riverdriver.Driver[pgx.Tx]), createBundle func(client TClient, tx pgx.Tx) apibundle.EndpointBundle, createHandler func(t *testing.T, bundle apibundle.EndpointBundle) http.Handler, testRunner func(exec riverdriver.Executor, makeAPICall APICallFunc)) { +func RunIntegrationTest[TClient any](t *testing.T, createClient func(t *testing.T, logger *slog.Logger) (TClient, riverdriver.Driver[pgx.Tx]), createBundle func(client TClient, tx pgx.Tx) uiendpoints.Bundle, createHandler func(t *testing.T, bundle uiendpoints.Bundle) http.Handler, testRunner func(exec riverdriver.Executor, makeAPICall APICallFunc)) { t.Helper() var ( diff --git a/internal/querycacher/query_cacher_test.go b/internal/querycacher/query_cacher_test.go index e4f59bcd..905666b7 100644 --- a/internal/querycacher/query_cacher_test.go +++ b/internal/querycacher/query_cacher_test.go @@ -6,14 +6,15 @@ import ( "time" "github.com/stretchr/testify/require" - "riverqueue.com/riverui/internal/riverinternaltest" - "riverqueue.com/riverui/internal/riverinternaltest/testfactory" "github.com/riverqueue/river/riverdriver" "github.com/riverqueue/river/riverdriver/riverpgxv5" "github.com/riverqueue/river/rivershared/riversharedtest" "github.com/riverqueue/river/rivershared/startstoptest" "github.com/riverqueue/river/rivertype" + + "riverqueue.com/riverui/internal/riverinternaltest" + "riverqueue.com/riverui/internal/riverinternaltest/testfactory" ) func TestQueryCacher(t *testing.T) { diff --git a/internal/riveruicmd/auth_middleware_test.go b/internal/riveruicmd/auth_middleware_test.go index 408c4112..c153a2f7 100644 --- a/internal/riveruicmd/auth_middleware_test.go +++ b/internal/riveruicmd/auth_middleware_test.go @@ -11,12 +11,13 @@ import ( "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "github.com/stretchr/testify/require" - "riverqueue.com/riverui" - "riverqueue.com/riverui/internal/apibundle" "github.com/riverqueue/river" "github.com/riverqueue/river/riverdriver/riverpgxv5" "github.com/riverqueue/river/rivershared/riversharedtest" + + "riverqueue.com/riverui" + "riverqueue.com/riverui/uiendpoints" ) func TestAuthMiddleware(t *testing.T) { @@ -38,7 +39,7 @@ func TestAuthMiddleware(t *testing.T) { func(dbPool *pgxpool.Pool) (*river.Client[pgx.Tx], error) { return river.NewClient(riverpgxv5.New(dbPool), &river.Config{}) }, - func(client *river.Client[pgx.Tx]) apibundle.EndpointBundle { + func(client *river.Client[pgx.Tx]) uiendpoints.Bundle { return riverui.NewEndpoints(client, nil) }, ) diff --git a/internal/riveruicmd/riveruicmd.go b/internal/riveruicmd/riveruicmd.go index c1c63900..8facc522 100644 --- a/internal/riveruicmd/riveruicmd.go +++ b/internal/riveruicmd/riveruicmd.go @@ -16,18 +16,19 @@ import ( "github.com/jackc/pgx/v5/pgxpool" "github.com/rs/cors" sloghttp "github.com/samber/slog-http" - "riverqueue.com/riverui" - "riverqueue.com/riverui/internal/apibundle" - "riverqueue.com/riverui/internal/authmiddleware" "github.com/riverqueue/apiframe/apimiddleware" + + "riverqueue.com/riverui" + "riverqueue.com/riverui/internal/authmiddleware" + "riverqueue.com/riverui/uiendpoints" ) type BundleOpts struct { JobListHideArgsByDefault bool } -func Run[TClient any](createClient func(*pgxpool.Pool) (TClient, error), createBundle func(TClient) apibundle.EndpointBundle) { +func Run[TClient any](createClient func(*pgxpool.Pool) (TClient, error), createBundle func(TClient) uiendpoints.Bundle) { ctx := context.Background() logger := slog.New(getLogHandler(&slog.HandlerOptions{ @@ -128,7 +129,7 @@ type initServerResult struct { uiHandler *riverui.Handler // River UI handler } -func initServer[TClient any](ctx context.Context, logger *slog.Logger, pathPrefix string, createClient func(*pgxpool.Pool) (TClient, error), createBundler func(TClient) apibundle.EndpointBundle) (*initServerResult, error) { +func initServer[TClient any](ctx context.Context, logger *slog.Logger, pathPrefix string, createClient func(*pgxpool.Pool) (TClient, error), createBundler func(TClient) uiendpoints.Bundle) (*initServerResult, error) { if !strings.HasPrefix(pathPrefix, "/") || pathPrefix == "" { return nil, fmt.Errorf("invalid path prefix: %s", pathPrefix) } diff --git a/internal/riveruicmd/riveruicmd_test.go b/internal/riveruicmd/riveruicmd_test.go index d8e502ac..4b9de38c 100644 --- a/internal/riveruicmd/riveruicmd_test.go +++ b/internal/riveruicmd/riveruicmd_test.go @@ -13,12 +13,13 @@ import ( "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "github.com/stretchr/testify/require" - "riverqueue.com/riverui" - "riverqueue.com/riverui/internal/apibundle" "github.com/riverqueue/river" "github.com/riverqueue/river/riverdriver/riverpgxv5" "github.com/riverqueue/river/rivershared/riversharedtest" + + "riverqueue.com/riverui" + "riverqueue.com/riverui/uiendpoints" ) func TestInitServer(t *testing.T) { @@ -40,7 +41,7 @@ func TestInitServer(t *testing.T) { func(dbPool *pgxpool.Pool) (*river.Client[pgx.Tx], error) { return river.NewClient(riverpgxv5.New(dbPool), &river.Config{}) }, - func(client *river.Client[pgx.Tx]) apibundle.EndpointBundle { + func(client *river.Client[pgx.Tx]) uiendpoints.Bundle { return riverui.NewEndpoints(client, nil) }, ) diff --git a/riverproui/cmd/riverproui/main.go b/riverproui/cmd/riverproui/main.go index 459b20fc..d0303a9a 100644 --- a/riverproui/cmd/riverproui/main.go +++ b/riverproui/cmd/riverproui/main.go @@ -3,12 +3,13 @@ package main import ( "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" - "riverqueue.com/riverui/internal/apibundle" - "riverqueue.com/riverui/internal/riveruicmd" - "riverqueue.com/riverui/riverproui" "riverqueue.com/riverpro" "riverqueue.com/riverpro/driver/riverpropgxv5" + + "riverqueue.com/riverui/internal/riveruicmd" + "riverqueue.com/riverui/riverproui" + "riverqueue.com/riverui/uiendpoints" ) func main() { @@ -16,7 +17,7 @@ func main() { func(dbPool *pgxpool.Pool) (*riverpro.Client[pgx.Tx], error) { return riverpro.NewClient(riverpropgxv5.New(dbPool), &riverpro.Config{}) }, - func(client *riverpro.Client[pgx.Tx]) apibundle.EndpointBundle { + func(client *riverpro.Client[pgx.Tx]) uiendpoints.Bundle { return riverproui.NewEndpoints(client, nil) }, ) diff --git a/riverproui/endpoints.go b/riverproui/endpoints.go index 015a251c..c6592f41 100644 --- a/riverproui/endpoints.go +++ b/riverproui/endpoints.go @@ -5,15 +5,16 @@ import ( "log/slog" "net/http" - "riverqueue.com/riverui" - "riverqueue.com/riverui/internal/apibundle" - "riverqueue.com/riverui/riverproui/internal/prohandler" - "github.com/riverqueue/apiframe/apiendpoint" "github.com/riverqueue/river/rivershared/baseservice" "riverqueue.com/riverpro" prodriver "riverqueue.com/riverpro/driver" + + "riverqueue.com/riverui" + "riverqueue.com/riverui/internal/apibundle" + "riverqueue.com/riverui/riverproui/internal/prohandler" + "riverqueue.com/riverui/uiendpoints" ) type EndpointsOpts[TTx any] struct { @@ -22,7 +23,7 @@ type EndpointsOpts[TTx any] struct { Tx *TTx } -func NewEndpoints[TTx any](client *riverpro.Client[TTx], opts *EndpointsOpts[TTx]) apibundle.EndpointBundle { +func NewEndpoints[TTx any](client *riverpro.Client[TTx], opts *EndpointsOpts[TTx]) uiendpoints.Bundle { if opts == nil { opts = &EndpointsOpts[TTx]{} } @@ -38,13 +39,13 @@ func NewEndpoints[TTx any](client *riverpro.Client[TTx], opts *EndpointsOpts[TTx } type endpoints[TTx any] struct { - bundleOpts *apibundle.EndpointBundleOpts + bundleOpts *uiendpoints.BundleOpts client *riverpro.Client[TTx] proOpts *EndpointsOpts[TTx] - ossEndpoints apibundle.EndpointBundle + ossEndpoints uiendpoints.Bundle } -func (e *endpoints[TTx]) Configure(bundleOpts *apibundle.EndpointBundleOpts) { +func (e *endpoints[TTx]) Configure(bundleOpts *uiendpoints.BundleOpts) { e.bundleOpts = bundleOpts e.ossEndpoints.Configure(bundleOpts) } diff --git a/riverproui/internal/prohandler/pro_handler_api_endpoints.go b/riverproui/internal/prohandler/pro_handler_api_endpoints.go index efce64f6..ed00eec8 100644 --- a/riverproui/internal/prohandler/pro_handler_api_endpoints.go +++ b/riverproui/internal/prohandler/pro_handler_api_endpoints.go @@ -8,9 +8,6 @@ import ( "strconv" "time" - "riverqueue.com/riverui/internal/apibundle" - "riverqueue.com/riverui/riverproui/internal/uitype" - "github.com/riverqueue/apiframe/apiendpoint" "github.com/riverqueue/apiframe/apierror" "github.com/riverqueue/river/rivershared/util/ptrutil" @@ -19,6 +16,9 @@ import ( "riverqueue.com/riverpro" riverprodriver "riverqueue.com/riverpro/driver" + + "riverqueue.com/riverui/internal/apibundle" + "riverqueue.com/riverui/riverproui/internal/uitype" ) type ProAPIBundle[TTx any] struct { diff --git a/riverproui/pro_handler_test.go b/riverproui/pro_handler_test.go index 5c7ec103..05ad5d2f 100644 --- a/riverproui/pro_handler_test.go +++ b/riverproui/pro_handler_test.go @@ -11,17 +11,18 @@ import ( "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/stretchr/testify/require" - "riverqueue.com/riverui" - "riverqueue.com/riverui/internal/apibundle" - "riverqueue.com/riverui/internal/handlertest" - "riverqueue.com/riverui/internal/riverinternaltest" - "riverqueue.com/riverui/internal/riverinternaltest/testfactory" "github.com/riverqueue/river" "github.com/riverqueue/river/riverdriver" "riverqueue.com/riverpro" "riverqueue.com/riverpro/driver/riverpropgxv5" + + "riverqueue.com/riverui" + "riverqueue.com/riverui/internal/handlertest" + "riverqueue.com/riverui/internal/riverinternaltest" + "riverqueue.com/riverui/internal/riverinternaltest/testfactory" + "riverqueue.com/riverui/uiendpoints" ) type noOpArgs struct { @@ -66,11 +67,11 @@ func mustMarshalJSON(t *testing.T, v any) []byte { func TestProHandlerIntegration(t *testing.T) { t.Parallel() - createBundle := func(client *riverpro.Client[pgx.Tx], tx pgx.Tx) apibundle.EndpointBundle { + createBundle := func(client *riverpro.Client[pgx.Tx], tx pgx.Tx) uiendpoints.Bundle { return NewEndpoints(client, &EndpointsOpts[pgx.Tx]{Tx: &tx}) } - createHandler := func(t *testing.T, bundle apibundle.EndpointBundle) http.Handler { + createHandler := func(t *testing.T, bundle uiendpoints.Bundle) http.Handler { t.Helper() logger := riverinternaltest.Logger(t) diff --git a/uiendpoints/bundle.go b/uiendpoints/bundle.go new file mode 100644 index 00000000..28baae09 --- /dev/null +++ b/uiendpoints/bundle.go @@ -0,0 +1,29 @@ +package uiendpoints + +import ( + "log/slog" + "net/http" + + "github.com/riverqueue/apiframe/apiendpoint" + "github.com/riverqueue/river/rivershared/baseservice" +) + +type BundleOpts struct { + JobListHideArgsByDefault bool +} + +// Bundle is a collection of API endpoints and features for a riverui.Handler. +// A Bundle must be provided to the Handler via the `Endpoints` option of +// `HandlerOpts`. +// +// Two constructors are provided: +// +// - `riverui.NewEndpoints` returns the open source riverui bundle +// - `riverproui.NewEndpoints` returns the Pro-specific bundle with Pro APIs and +// features enabled. The `riverproui` package is a separate module that +// requires the `riverpro` module to be installed. +type Bundle interface { + Configure(bundleOpts *BundleOpts) + MountEndpoints(archetype *baseservice.Archetype, logger *slog.Logger, mux *http.ServeMux, mountOpts *apiendpoint.MountOpts, extensions map[string]bool) []apiendpoint.EndpointInterface + Validate() error +}