Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ on:
pull_request:
branches:
- "master"
- "*"
workflow_dispatch:
inputs:
ref:
Expand Down
1 change: 1 addition & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,4 @@ formatters:
- Default
- Prefix(github.com/riverqueue)
- Prefix(riverqueue.com/riverpro)
- Prefix(riverqueue.com/riverui)
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions Dockerfile.pro
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions cmd/riverui/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@ 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() {
riveruicmd.Run(
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)
},
)
Expand Down
3 changes: 2 additions & 1 deletion example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
23 changes: 16 additions & 7 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,43 @@ import (
"path/filepath"
"strings"

"riverqueue.com/riverui/internal/apibundle"

"github.com/riverqueue/apiframe/apiendpoint"
"github.com/riverqueue/apiframe/apimiddleware"
"github.com/riverqueue/apiframe/apitype"
"github.com/riverqueue/river"
"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.
Tx *TTx
}

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]{}
}
Expand All @@ -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
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
})

Expand Down
6 changes: 3 additions & 3 deletions handler_api_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 {
Expand Down
7 changes: 4 additions & 3 deletions handler_api_endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 {
Expand Down
13 changes: 7 additions & 6 deletions handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,29 @@ 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) {
t.Parallel()

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)
Expand Down
12 changes: 0 additions & 12 deletions internal/apibundle/api_bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
}
7 changes: 4 additions & 3 deletions internal/handlertest/handlertest.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down
5 changes: 3 additions & 2 deletions internal/querycacher/query_cacher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
7 changes: 4 additions & 3 deletions internal/riveruicmd/auth_middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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)
},
)
Expand Down
11 changes: 6 additions & 5 deletions internal/riveruicmd/riveruicmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -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)
}
Expand Down
7 changes: 4 additions & 3 deletions internal/riveruicmd/riveruicmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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)
},
)
Expand Down
Loading
Loading