From 0ca55a0d895e0341f2a059209e2d899177148f16 Mon Sep 17 00:00:00 2001 From: David Thorpe Date: Tue, 16 Dec 2025 21:33:00 +0100 Subject: [PATCH 1/3] Updated to include frontend --- Makefile | 26 +++++++++++++++++--- cmd/pgmanager/server.go | 9 ++----- etc/Dockerfile | 5 ++-- etc/embed.go | 6 +++++ etc/go.mod | 3 +++ go.mod | 6 +++-- pkg/manager/httphandler/doc.go | 2 +- pkg/manager/httphandler/frontend.go | 17 +++++++++++++ pkg/manager/httphandler/frontend_excluded.go | 18 ++++++++++++++ pkg/manager/httphandler/httphandler.go | 2 +- wasm/pgmanager/main.go | 25 +++++++++++++++++++ wasm/pgmanager/wasmbuild.yaml | 9 +++++++ 12 files changed, 112 insertions(+), 16 deletions(-) create mode 100644 etc/embed.go create mode 100644 etc/go.mod create mode 100644 pkg/manager/httphandler/frontend.go create mode 100644 pkg/manager/httphandler/frontend_excluded.go create mode 100644 wasm/pgmanager/main.go create mode 100644 wasm/pgmanager/wasmbuild.yaml diff --git a/Makefile b/Makefile index 774795d..bf713e1 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ # Path parameters GO ?= $(shell which go 2>/dev/null) DOCKER ?= $(shell which docker 2>/dev/null) +WASMBUILD ?= $(shell which wasmbuild 2>/dev/null) BUILDDIR ?= build CMDDIR=$(wildcard cmd/*) +WASMDIR=$(wildcard wasm/*) # Set OS and Architecture ARCH ?= $(shell arch | tr A-Z a-z | sed 's/x86_64/amd64/' | sed 's/i386/amd64/' | sed 's/armv7l/arm/' | sed 's/aarch64/arm64/') @@ -16,7 +18,7 @@ BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitTag=$(shell git describe --t BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitBranch=$(shell git name-rev HEAD --name-only --always) BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitHash=$(shell git rev-parse HEAD) BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GoBuildTime=$(shell date -u '+%Y-%m-%dT%H:%M:%SZ') -BUILD_FLAGS = -ldflags "-s -w ${BUILD_LD_FLAGS}" +BUILD_FLAGS = -ldflags="-s -w ${BUILD_LD_FLAGS}" # Docker DOCKER_REPO ?= ghcr.io/mutablelogic/pgmanager @@ -29,8 +31,22 @@ all: tidy $(CMDDIR) # Rules for building .PHONY: $(CMDDIR) $(CMDDIR): go-dep mkdir - @echo 'building $@' - @$(GO) build $(BUILD_FLAGS) -o ${BUILDDIR}/$(shell basename $@) ./$@ + @echo 'go build $@' + @rm -rf ${BUILDDIR}/$(shell basename $@) + @$(GO) build -tags frontend $(BUILD_FLAGS) -o ${BUILDDIR}/$(shell basename $@) ./$@ + +# Rules for building +.PHONY: $(WASMDIR) +$(WASMDIR): go-dep wasmbuild-dep mkdir + @echo 'wasmbuild $@' + @$(GO) get github.com/djthorpe/go-wasmbuild/pkg/bootstrap github.com/djthorpe/go-wasmbuild/pkg/bootstrap/extra github.com/djthorpe/go-wasmbuild/pkg/mvc + @${WASMBUILD} build --go-flags='$(BUILD_FLAGS)' -o ${BUILDDIR}/wasm/$(shell basename $@) ./$@ && \ + mv ${BUILDDIR}/wasm/$(shell basename $@)/wasm_exec.html ${BUILDDIR}/wasm/$(shell basename $@)/index.html && \ + cp etc/embed.go ${BUILDDIR}/wasm/$(shell basename $@)/ + +# Build pgmanager with embedded frontend +.PHONY: pgmanager +pgmanager: wasm/pgmanager cmd/pgmanager # Build the docker image .PHONY: docker @@ -88,3 +104,7 @@ go-dep: .PHONY: docker-dep docker-dep: @test -f "${DOCKER}" && test -x "${DOCKER}" || (echo "Missing docker binary" && exit 1) + +.PHONE: wasmbuild-dep +wasmbuild-dep: + @test -f "${WASMBUILD}" && test -x "${WASMBUILD}" || (echo "Missing wasmbuild binary" && exit 1) \ No newline at end of file diff --git a/cmd/pgmanager/server.go b/cmd/pgmanager/server.go index cbfa38b..cb794d4 100644 --- a/cmd/pgmanager/server.go +++ b/cmd/pgmanager/server.go @@ -10,7 +10,6 @@ import ( "github.com/mutablelogic/go-pg" "github.com/mutablelogic/go-pg/pkg/manager" "github.com/mutablelogic/go-pg/pkg/manager/httphandler" - "github.com/mutablelogic/go-server/pkg/httpresponse" "github.com/mutablelogic/go-server/pkg/httpserver" ) @@ -75,12 +74,8 @@ func (cmd *RunServer) Run(ctx *Globals) error { // Register HTTP handlers router := http.NewServeMux() - httphandler.RegisterHandlers(router, ctx.HTTP.Prefix, manager) - - // Catch all handler returns a "not found" error - router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - _ = httpresponse.Error(w, httpresponse.ErrNotFound, r.URL.String()) - }) + httphandler.RegisterBackendHandlers(router, ctx.HTTP.Prefix, manager) + httphandler.RegisterFrontendHandler(router, "") // Create a TLS config var tlsconfig *tls.Config diff --git a/etc/Dockerfile b/etc/Dockerfile index 39dea6e..d73253c 100644 --- a/etc/Dockerfile +++ b/etc/Dockerfile @@ -7,7 +7,8 @@ ARG ARCH=amd64 FROM --platform=${OS}/${ARCH} golang:1.24 AS builder WORKDIR /usr/src/app COPY . . -RUN OS=${OS} ARCH=${ARCH} make cmd/pgmanager +RUN go install github.com/djthorpe/go-wasmbuild/cmd/wasmbuild@latest && \ + OS=${OS} ARCH=${ARCH} make pgmanager # Runtime stage FROM --platform=${OS}/${ARCH} debian:bookworm-slim @@ -21,5 +22,5 @@ RUN apt-get update && \ LABEL org.opencontainers.image.source=${SOURCE} # Entrypoint when running the server -EXPOSE 80 443 +EXPOSE 8080 ENTRYPOINT ["/usr/local/bin/pgmanager"] diff --git a/etc/embed.go b/etc/embed.go new file mode 100644 index 0000000..eac6e72 --- /dev/null +++ b/etc/embed.go @@ -0,0 +1,6 @@ +package frontend + +import "embed" + +//go:embed *.html *.js *.wasm *.png +var FS embed.FS diff --git a/etc/go.mod b/etc/go.mod new file mode 100644 index 0000000..e54d3b7 --- /dev/null +++ b/etc/go.mod @@ -0,0 +1,3 @@ +module github.com/mutablelogic/go-pg/frontend + +go 1.24.0 diff --git a/go.mod b/go.mod index 52db797..f633001 100644 --- a/go.mod +++ b/go.mod @@ -42,6 +42,7 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect @@ -74,15 +75,16 @@ require ( go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 // indirect go.opentelemetry.io/otel v1.39.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 // indirect go.opentelemetry.io/otel/metric v1.39.0 // indirect go.opentelemetry.io/otel/trace v1.39.0 // indirect - go.opentelemetry.io/proto/otlp v1.9.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect golang.org/x/crypto v0.46.0 // indirect golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.39.0 // indirect golang.org/x/text v0.32.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect + google.golang.org/grpc v1.75.1 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/pkg/manager/httphandler/doc.go b/pkg/manager/httphandler/doc.go index 2d4364c..2299798 100644 --- a/pkg/manager/httphandler/doc.go +++ b/pkg/manager/httphandler/doc.go @@ -3,7 +3,7 @@ // // Register all handlers with an http.ServeMux: // -// httphandler.RegisterHandlers(mux, "/api/v1", mgr) +// httphandler.RegisterBackendHandlers(mux, "/api/v1", mgr) // // This registers endpoints for roles, databases, schemas, objects, tablespaces, // extensions, connections, settings, statements, replication slots, and diff --git a/pkg/manager/httphandler/frontend.go b/pkg/manager/httphandler/frontend.go new file mode 100644 index 0000000..346ba84 --- /dev/null +++ b/pkg/manager/httphandler/frontend.go @@ -0,0 +1,17 @@ +//go:build frontend + +package httphandler + +import ( + "net/http" + + // Packages + frontend "github.com/mutablelogic/go-pg/build/wasm/pgmanager" +) + +// RegisterFrontendHandler registers the frontend static file handler +func RegisterFrontendHandler(router *http.ServeMux, prefix string) { + // Serve static files + fileServer := http.FileServer(http.FS(frontend.FS)) + router.Handle(joinPath(prefix, "/"), http.StripPrefix(prefix, fileServer)) +} diff --git a/pkg/manager/httphandler/frontend_excluded.go b/pkg/manager/httphandler/frontend_excluded.go new file mode 100644 index 0000000..3a4230f --- /dev/null +++ b/pkg/manager/httphandler/frontend_excluded.go @@ -0,0 +1,18 @@ +//go:build !frontend + +package httphandler + +import ( + "net/http" + + // Packages + "github.com/mutablelogic/go-server/pkg/httpresponse" +) + +// RegisterFrontendHandler registers a fallback handler when frontend is not included +func RegisterFrontendHandler(router *http.ServeMux, prefix string) { + // Catch all handler returns a "not found" error + router.HandleFunc(joinPath(prefix, "/"), func(w http.ResponseWriter, r *http.Request) { + _ = httpresponse.Error(w, httpresponse.ErrNotFound, r.URL.String()) + }) +} diff --git a/pkg/manager/httphandler/httphandler.go b/pkg/manager/httphandler/httphandler.go index 2746a10..74d8841 100644 --- a/pkg/manager/httphandler/httphandler.go +++ b/pkg/manager/httphandler/httphandler.go @@ -14,7 +14,7 @@ import ( /////////////////////////////////////////////////////////////////////////////// // PUBLIC METHODS -func RegisterHandlers(router *http.ServeMux, prefix string, manager *manager.Manager) { +func RegisterBackendHandlers(router *http.ServeMux, prefix string, manager *manager.Manager) { RegisterConnectionHandlers(router, prefix, manager) RegisterDatabaseHandlers(router, prefix, manager) RegisterExtensionHandlers(router, prefix, manager) diff --git a/wasm/pgmanager/main.go b/wasm/pgmanager/main.go new file mode 100644 index 0000000..b546fa0 --- /dev/null +++ b/wasm/pgmanager/main.go @@ -0,0 +1,25 @@ +package main + +import ( + // Packages + bs "github.com/djthorpe/go-wasmbuild/pkg/bootstrap" + bsextra "github.com/djthorpe/go-wasmbuild/pkg/bootstrap/extra" + mvc "github.com/djthorpe/go-wasmbuild/pkg/mvc" +) + +func main() { + // Navigation controller + controller := bsextra.NavbarController(navbar()) + + // Run the application + mvc.New(controller.Views()[0]).Run() +} + +func navbar() mvc.View { + return bs.NavBar("main", + bs.WithPosition(bs.Sticky|bs.Top), bs.WithTheme(bs.Dark), bs.WithSize(bs.Medium), + bs.NavItem("#roles", "Roles"), + ).Label( + bs.Icon("bootstrap-fill", mvc.WithClass("me-2")), "pgmanager", + ) +} diff --git a/wasm/pgmanager/wasmbuild.yaml b/wasm/pgmanager/wasmbuild.yaml new file mode 100644 index 0000000..eb92fc4 --- /dev/null +++ b/wasm/pgmanager/wasmbuild.yaml @@ -0,0 +1,9 @@ +vars: + Title: "pgmanager" + Header: | + + + + + + From 321e070f055aa055c48133124881656205ab46c5 Mon Sep 17 00:00:00 2001 From: David Thorpe Date: Wed, 17 Dec 2025 07:32:23 +0100 Subject: [PATCH 2/3] Updates --- Makefile | 5 ++++- etc/go.mod | 3 --- go.mod | 7 +++++++ go.sum | 4 ++++ 4 files changed, 15 insertions(+), 4 deletions(-) delete mode 100644 etc/go.mod diff --git a/Makefile b/Makefile index bf713e1..a4eb999 100644 --- a/Makefile +++ b/Makefile @@ -84,8 +84,11 @@ mkdir: @install -d $(BUILDDIR) .PHONY: go-dep tidy -tidy: +tidy: mkdir @echo 'go tidy' + @install -d ${BUILDDIR}/wasm/pgmanager + @cp -n etc/embed.go ${BUILDDIR}/wasm/pgmanager/ 2>/dev/null || true + @echo 'module github.com/mutablelogic/go-pg/build/wasm/pgmanager' > ${BUILDDIR}/wasm/pgmanager/go.mod @$(GO) mod tidy .PHONY: clean diff --git a/etc/go.mod b/etc/go.mod deleted file mode 100644 index e54d3b7..0000000 --- a/etc/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/mutablelogic/go-pg/frontend - -go 1.24.0 diff --git a/go.mod b/go.mod index f633001..3007ce2 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,11 @@ toolchain go1.24.2 require ( github.com/alecthomas/kong v1.13.0 + github.com/djthorpe/go-wasmbuild v0.0.1 github.com/docker/go-connections v0.6.0 github.com/jackc/pgx/v5 v5.7.6 github.com/mutablelogic/go-client v1.2.2 + github.com/mutablelogic/go-pg/build/wasm/pgmanager v0.0.0-00010101000000-000000000000 github.com/mutablelogic/go-server v1.5.17 github.com/prometheus/client_golang v1.23.2 github.com/stretchr/testify v1.11.1 @@ -58,6 +60,7 @@ require ( github.com/moby/term v0.5.2 // indirect github.com/morikuni/aec v1.1.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mutablelogic/go-tokenizer v0.0.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -79,6 +82,7 @@ require ( go.opentelemetry.io/otel/trace v1.39.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect golang.org/x/crypto v0.46.0 // indirect + golang.org/x/net v0.47.0 // indirect golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.39.0 // indirect golang.org/x/text v0.32.0 // indirect @@ -91,3 +95,6 @@ require ( // Redirect old module path to this module (for transitive dependencies) replace github.com/djthorpe/go-pg => ./ + +// Frontend embedded files (local path, built by make wasm/pgmanager) +replace github.com/mutablelogic/go-pg/build/wasm/pgmanager => ./build/wasm/pgmanager diff --git a/go.sum b/go.sum index d1d72c0..eb8e566 100644 --- a/go.sum +++ b/go.sum @@ -41,6 +41,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djthorpe/go-errors v1.0.3 h1:GZeMPkC1mx2vteXLI/gvxZS0Ee9zxzwD1mcYyKU5jD0= github.com/djthorpe/go-errors v1.0.3/go.mod h1:HtfrZnMd6HsX75Mtbv9Qcnn0BqOrrFArvCaj3RMnZhY= +github.com/djthorpe/go-wasmbuild v0.0.1 h1:HoPNhNcrK5S0ze2TS46NouoAyXPqupgQImNfwaM1b0o= +github.com/djthorpe/go-wasmbuild v0.0.1/go.mod h1:T3vqsVbmzws0VG50oXY5OiQMDIdBQsgYRjkoVIedPFM= github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM= github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= @@ -130,6 +132,8 @@ github.com/mutablelogic/go-client v1.2.2 h1:ZKIQFL4qYydyyBb2s3BaMUwIF3dlA5HCOTDN github.com/mutablelogic/go-client v1.2.2/go.mod h1:Y31sWrM22cSWiiOtvkc0MHSpFt5hMsk/CsjJ0d8iB10= github.com/mutablelogic/go-server v1.5.17 h1:NXuP8IWIM3DLlu/I375fK8pq+OIYHil3Xun1GGklUWM= github.com/mutablelogic/go-server v1.5.17/go.mod h1:HCX8WZtE3RXR4i+npBvCdILfnBelomDIe8/B68O/MA4= +github.com/mutablelogic/go-tokenizer v0.0.1 h1:3gSF+zoMq4tLpH+XYawkVUb7qmWuYNCez1CTs/iX3mU= +github.com/mutablelogic/go-tokenizer v0.0.1/go.mod h1:zdAyIhfqUKxFXb8MwChbXNwMOZt/5NlUylmx6Qjr4v8= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= From 139630bc7dc51314932bd90c3c794c2af20a6586 Mon Sep 17 00:00:00 2001 From: David Thorpe Date: Wed, 17 Dec 2025 07:34:27 +0100 Subject: [PATCH 3/3] Fiixed typo --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a4eb999..1ff4a2d 100644 --- a/Makefile +++ b/Makefile @@ -108,6 +108,6 @@ go-dep: docker-dep: @test -f "${DOCKER}" && test -x "${DOCKER}" || (echo "Missing docker binary" && exit 1) -.PHONE: wasmbuild-dep +.PHONY: wasmbuild-dep wasmbuild-dep: @test -f "${WASMBUILD}" && test -x "${WASMBUILD}" || (echo "Missing wasmbuild binary" && exit 1) \ No newline at end of file