Split backend/frontend and refactor

This commit is contained in:
Marcus Kida 2026-02-19 17:00:59 +01:00
parent 2a2e98901c
commit efe55c5990
63 changed files with 35 additions and 29 deletions

View file

@ -1,10 +1,11 @@
root = "." root = "."
[build] [build]
cmd = "go build -o ./tmp/dmrmap ." cmd = "cd backend && go build -o /app/tmp/dmrmap ."
bin = "./tmp/dmrmap" bin = "./tmp/dmrmap"
include_ext = ["go"] include_ext = ["go"]
exclude_dir = ["tmp", "static", "data", "migrations", "src", "node_modules"] include_dir = ["backend"]
exclude_dir = ["tmp", "frontend"]
delay = 500 delay = 500
[misc] [misc]

7
.gitignore vendored
View file

@ -1,9 +1,8 @@
tmp/ tmp/
data/
dmrmap dmrmap
compose.override.yml compose.override.yml
.env .env
static/talkgroups.json frontend/static/talkgroups.json
node_modules/ node_modules/
static/app.js frontend/static/app.js
static/app.js.map frontend/static/app.js.map

View file

@ -1,29 +1,29 @@
FROM node:22-alpine AS frontend FROM node:22-alpine AS frontend
WORKDIR /build WORKDIR /build
COPY package.json package-lock.json ./ COPY frontend/package.json frontend/package-lock.json ./
RUN npm ci RUN npm ci
COPY src/ ./src/ COPY frontend/src/ ./src/
COPY tsconfig.json ./ COPY frontend/tsconfig.json ./
RUN npm run build:prod RUN npm run build:prod
FROM golang:1.25-alpine AS builder FROM golang:1.25-alpine AS builder
RUN apk add --no-cache git RUN apk add --no-cache git
WORKDIR /build WORKDIR /build
COPY .git ./.git COPY .git ./.git
COPY go.mod go.sum ./ COPY backend/go.mod backend/go.sum ./
RUN go mod download RUN go mod download
COPY *.go ./ COPY backend/*.go ./
COPY migrations/ ./migrations/ COPY backend/migrations/ ./migrations/
RUN CGO_ENABLED=0 go build -ldflags "-X main.version=$(git rev-parse --short HEAD)" -o dmrmap . RUN CGO_ENABLED=0 go build -ldflags "-X main.version=$(git rev-parse --short HEAD)" -o dmrmap .
FROM alpine:3.19 FROM alpine:3.19
WORKDIR /app WORKDIR /app
COPY --from=builder /build/dmrmap . COPY --from=builder /build/dmrmap .
COPY --from=builder /build/migrations/ ./migrations/ COPY --from=builder /build/migrations/ ./migrations/
COPY static/ ./static/ COPY frontend/static/ ./static/
COPY --from=frontend /build/static/app.js ./static/app.js COPY --from=frontend /build/static/app.js ./static/app.js
COPY rptrs.json . COPY backend/data/rptrs.json .
COPY bmrptrs.json . COPY backend/data/bmrptrs.json .
RUN wget -qO static/talkgroups.json https://api.brandmeister.network/v2/talkgroup RUN wget -qO static/talkgroups.json https://api.brandmeister.network/v2/talkgroup
EXPOSE 8080 EXPOSE 8080
CMD ["./dmrmap"] CMD ["./dmrmap"]

View file

@ -3,6 +3,6 @@ RUN apk add --no-cache nodejs npm
RUN go install github.com/air-verse/air@latest RUN go install github.com/air-verse/air@latest
RUN wget -qO /usr/local/share/talkgroups.json https://api.brandmeister.network/v2/talkgroup RUN wget -qO /usr/local/share/talkgroups.json https://api.brandmeister.network/v2/talkgroup
WORKDIR /app WORKDIR /app
CMD cp -n /usr/local/share/talkgroups.json static/talkgroups.json 2>/dev/null; \ CMD cp -n /usr/local/share/talkgroups.json frontend/static/talkgroups.json 2>/dev/null; \
npm install --silent && npm run watch & \ cd frontend && npm install --silent && npm run watch & \
air air

View file

@ -7,6 +7,7 @@ import (
"log" "log"
"net/http" "net/http"
"net/url" "net/url"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -24,9 +25,10 @@ func adminAuth(token string, next http.Handler) http.Handler {
}) })
} }
func handleAdminPage() http.HandlerFunc { func handleAdminPage(staticDir string) http.HandlerFunc {
adminPath := filepath.Join(staticDir, "admin.html")
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "static/admin.html") http.ServeFile(w, r, adminPath)
} }
} }

View file

@ -13,6 +13,8 @@ func main() {
jsonPath := envOr("JSON_PATH", "rptrs.json") jsonPath := envOr("JSON_PATH", "rptrs.json")
bmrptrsPath := envOr("BMRPTRS_PATH", "bmrptrs.json") bmrptrsPath := envOr("BMRPTRS_PATH", "bmrptrs.json")
addr := envOr("LISTEN_ADDR", ":8080") addr := envOr("LISTEN_ADDR", ":8080")
staticDir := envOr("STATIC_DIR", "static")
migrationsDir := envOr("MIGRATIONS_DIR", "migrations")
db, err := openDB(dsn) db, err := openDB(dsn)
if err != nil { if err != nil {
@ -20,7 +22,7 @@ func main() {
} }
defer db.Close() defer db.Close()
if err := runMigrations(db); err != nil { if err := runMigrations(db, migrationsDir); err != nil {
log.Fatalf("Failed to run migrations: %v", err) log.Fatalf("Failed to run migrations: %v", err)
} }
@ -43,7 +45,7 @@ func main() {
mux.HandleFunc("/api/version", handleVersion()) mux.HandleFunc("/api/version", handleVersion())
if adminToken := os.Getenv("ADMIN_TOKEN"); adminToken != "" { if adminToken := os.Getenv("ADMIN_TOKEN"); adminToken != "" {
mux.HandleFunc("/admin/", handleAdminPage()) mux.HandleFunc("/admin/", handleAdminPage(staticDir))
adminAPI := http.NewServeMux() adminAPI := http.NewServeMux()
adminAPI.HandleFunc("/admin/api/repeaters", handleAdminRepeaters(db)) adminAPI.HandleFunc("/admin/api/repeaters", handleAdminRepeaters(db))
adminAPI.HandleFunc("/admin/api/repeaters/update", handleAdminUpdateRepeater(db)) adminAPI.HandleFunc("/admin/api/repeaters/update", handleAdminUpdateRepeater(db))
@ -55,7 +57,7 @@ func main() {
log.Println("Admin interface enabled at /admin/") log.Println("Admin interface enabled at /admin/")
} }
mux.Handle("/", http.FileServer(http.Dir("static"))) mux.Handle("/", http.FileServer(http.Dir(staticDir)))
log.Printf("Listening on %s", addr) log.Printf("Listening on %s", addr)
log.Fatal(http.ListenAndServe(addr, mux)) log.Fatal(http.ListenAndServe(addr, mux))

View file

@ -7,11 +7,11 @@ import (
"github.com/pressly/goose/v3" "github.com/pressly/goose/v3"
) )
func runMigrations(db *sql.DB) error { func runMigrations(db *sql.DB, dir string) error {
if err := goose.SetDialect("postgres"); err != nil { if err := goose.SetDialect("postgres"); err != nil {
return err return err
} }
if err := goose.Up(db, "migrations"); err != nil { if err := goose.Up(db, dir); err != nil {
return err return err
} }
log.Println("Database migrations applied successfully") log.Println("Database migrations applied successfully")

View file

@ -20,15 +20,17 @@ services:
- .:/app - .:/app
- go-mod-cache:/go/pkg/mod - go-mod-cache:/go/pkg/mod
- go-build-cache:/root/.cache/go-build - go-build-cache:/root/.cache/go-build
- node_modules:/app/node_modules - node_modules:/app/frontend/node_modules
depends_on: depends_on:
- postgres - postgres
environment: environment:
- DATABASE_URL=postgres://dmrmap:dmrmap@postgres:5432/dmrmap?sslmode=disable - DATABASE_URL=postgres://dmrmap:dmrmap@postgres:5432/dmrmap?sslmode=disable
- JSON_PATH=/app/rptrs.json - JSON_PATH=/app/backend/data/rptrs.json
- BMRPTRS_PATH=/app/bmrptrs.json - BMRPTRS_PATH=/app/backend/data/bmrptrs.json
- LISTEN_ADDR=:8080 - LISTEN_ADDR=:8080
- ADMIN_TOKEN=adminparty - ADMIN_TOKEN=adminparty
- STATIC_DIR=/app/frontend/static
- MIGRATIONS_DIR=/app/backend/migrations
volumes: volumes:
go-mod-cache: go-mod-cache:

View file

@ -1,10 +1,10 @@
services: services:
test: test:
image: node:22-alpine image: node:22-alpine
working_dir: /app working_dir: /app/frontend
volumes: volumes:
- .:/app - .:/app
- node_modules_test:/app/node_modules - node_modules_test:/app/frontend/node_modules
command: sh -c "npm install --silent && npm test" command: sh -c "npm install --silent && npm test"
volumes: volumes:

View file

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

Before

Width:  |  Height:  |  Size: 618 B

After

Width:  |  Height:  |  Size: 618 B