From efe55c5990cd7759d6c641c27d4666ec3d27c169 Mon Sep 17 00:00:00 2001 From: Marcus Kida Date: Thu, 19 Feb 2026 17:00:59 +0100 Subject: [PATCH] Split backend/frontend and refactor --- .air.toml | 5 +++-- .gitignore | 7 +++---- Dockerfile | 18 +++++++++--------- Dockerfile.dev | 4 ++-- admin.go => backend/admin.go | 6 ++++-- bmdevice.go => backend/bmdevice.go | 0 bmrptrs.json => backend/data/bmrptrs.json | 0 rptrs.json => backend/data/rptrs.json | 0 db.go => backend/db.go | 0 go.mod => backend/go.mod | 0 go.sum => backend/go.sum | 0 handlers.go => backend/handlers.go | 0 main.go => backend/main.go | 8 +++++--- migrate.go => backend/migrate.go | 4 ++-- .../migrations}/001_initial_schema.sql | 0 .../migrations}/002_add_bm_device_fields.sql | 0 .../migrations}/003_networks_array.sql | 0 .../migrations}/005_changelog.sql | 0 seed.go => backend/seed.go | 0 compose.dev.yml | 8 +++++--- compose.test.yml | 4 ++-- .../package-lock.json | 0 package.json => frontend/package.json | 0 {src => frontend/src}/cps-anytone.test.ts | 0 {src => frontend/src}/cps-anytone.ts | 0 {src => frontend/src}/cps-motorola.test.ts | 0 {src => frontend/src}/cps-motorola.ts | 0 {src => frontend/src}/filters.test.ts | 0 {src => frontend/src}/filters.ts | 0 {src => frontend/src}/format.test.ts | 0 {src => frontend/src}/format.ts | 0 {src => frontend/src}/geo.test.ts | 0 {src => frontend/src}/geo.ts | 0 {src => frontend/src}/globals.d.ts | 0 {src => frontend/src}/main.ts | 0 {src => frontend/src}/popup.test.ts | 0 {src => frontend/src}/popup.ts | 0 {src => frontend/src}/talkgroups.test.ts | 0 {src => frontend/src}/talkgroups.ts | 0 {src => frontend/src}/types.ts | 0 {static => frontend/static}/admin.html | 0 {static => frontend/static}/datenschutz.html | 0 {static => frontend/static}/i18n.js | 0 {static => frontend/static}/impressum.html | 0 {static => frontend/static}/index.html | 0 .../i18next-browser-languagedetector.min.js | 0 .../static}/lib/i18next-http-backend.min.js | 0 .../static}/lib/i18next.min.js | 0 .../static}/lib/images/marker-icon-2x.png | Bin .../static}/lib/images/marker-icon.png | Bin .../static}/lib/images/marker-shadow.png | Bin {static => frontend/static}/lib/leaflet.css | 0 {static => frontend/static}/lib/leaflet.js | 0 .../static}/lib/socket.io.min.js | 0 {static => frontend/static}/locales/de.json | 0 {static => frontend/static}/locales/en.json | 0 {static => frontend/static}/locales/es.json | 0 {static => frontend/static}/locales/fr.json | 0 {static => frontend/static}/locales/it.json | 0 {static => frontend/static}/locales/pl.json | 0 {static => frontend/static}/style.css | 0 tsconfig.json => frontend/tsconfig.json | 0 vitest.config.ts => frontend/vitest.config.ts | 0 63 files changed, 35 insertions(+), 29 deletions(-) rename admin.go => backend/admin.go (98%) rename bmdevice.go => backend/bmdevice.go (100%) rename bmrptrs.json => backend/data/bmrptrs.json (100%) rename rptrs.json => backend/data/rptrs.json (100%) rename db.go => backend/db.go (100%) rename go.mod => backend/go.mod (100%) rename go.sum => backend/go.sum (100%) rename handlers.go => backend/handlers.go (100%) rename main.go => backend/main.go (89%) rename migrate.go => backend/migrate.go (71%) rename {migrations => backend/migrations}/001_initial_schema.sql (100%) rename {migrations => backend/migrations}/002_add_bm_device_fields.sql (100%) rename {migrations => backend/migrations}/003_networks_array.sql (100%) rename {migrations => backend/migrations}/005_changelog.sql (100%) rename seed.go => backend/seed.go (100%) rename package-lock.json => frontend/package-lock.json (100%) rename package.json => frontend/package.json (100%) rename {src => frontend/src}/cps-anytone.test.ts (100%) rename {src => frontend/src}/cps-anytone.ts (100%) rename {src => frontend/src}/cps-motorola.test.ts (100%) rename {src => frontend/src}/cps-motorola.ts (100%) rename {src => frontend/src}/filters.test.ts (100%) rename {src => frontend/src}/filters.ts (100%) rename {src => frontend/src}/format.test.ts (100%) rename {src => frontend/src}/format.ts (100%) rename {src => frontend/src}/geo.test.ts (100%) rename {src => frontend/src}/geo.ts (100%) rename {src => frontend/src}/globals.d.ts (100%) rename {src => frontend/src}/main.ts (100%) rename {src => frontend/src}/popup.test.ts (100%) rename {src => frontend/src}/popup.ts (100%) rename {src => frontend/src}/talkgroups.test.ts (100%) rename {src => frontend/src}/talkgroups.ts (100%) rename {src => frontend/src}/types.ts (100%) rename {static => frontend/static}/admin.html (100%) rename {static => frontend/static}/datenschutz.html (100%) rename {static => frontend/static}/i18n.js (100%) rename {static => frontend/static}/impressum.html (100%) rename {static => frontend/static}/index.html (100%) rename {static => frontend/static}/lib/i18next-browser-languagedetector.min.js (100%) rename {static => frontend/static}/lib/i18next-http-backend.min.js (100%) rename {static => frontend/static}/lib/i18next.min.js (100%) rename {static => frontend/static}/lib/images/marker-icon-2x.png (100%) rename {static => frontend/static}/lib/images/marker-icon.png (100%) rename {static => frontend/static}/lib/images/marker-shadow.png (100%) rename {static => frontend/static}/lib/leaflet.css (100%) rename {static => frontend/static}/lib/leaflet.js (100%) rename {static => frontend/static}/lib/socket.io.min.js (100%) rename {static => frontend/static}/locales/de.json (100%) rename {static => frontend/static}/locales/en.json (100%) rename {static => frontend/static}/locales/es.json (100%) rename {static => frontend/static}/locales/fr.json (100%) rename {static => frontend/static}/locales/it.json (100%) rename {static => frontend/static}/locales/pl.json (100%) rename {static => frontend/static}/style.css (100%) rename tsconfig.json => frontend/tsconfig.json (100%) rename vitest.config.ts => frontend/vitest.config.ts (100%) diff --git a/.air.toml b/.air.toml index 349d796..63d9d25 100644 --- a/.air.toml +++ b/.air.toml @@ -1,10 +1,11 @@ root = "." [build] - cmd = "go build -o ./tmp/dmrmap ." + cmd = "cd backend && go build -o /app/tmp/dmrmap ." bin = "./tmp/dmrmap" include_ext = ["go"] - exclude_dir = ["tmp", "static", "data", "migrations", "src", "node_modules"] + include_dir = ["backend"] + exclude_dir = ["tmp", "frontend"] delay = 500 [misc] diff --git a/.gitignore b/.gitignore index ceaf5f9..eab9bf6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,8 @@ tmp/ -data/ dmrmap compose.override.yml .env -static/talkgroups.json +frontend/static/talkgroups.json node_modules/ -static/app.js -static/app.js.map +frontend/static/app.js +frontend/static/app.js.map diff --git a/Dockerfile b/Dockerfile index 9236a60..b3ecc87 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,29 +1,29 @@ FROM node:22-alpine AS frontend WORKDIR /build -COPY package.json package-lock.json ./ +COPY frontend/package.json frontend/package-lock.json ./ RUN npm ci -COPY src/ ./src/ -COPY tsconfig.json ./ +COPY frontend/src/ ./src/ +COPY frontend/tsconfig.json ./ RUN npm run build:prod FROM golang:1.25-alpine AS builder RUN apk add --no-cache git WORKDIR /build COPY .git ./.git -COPY go.mod go.sum ./ +COPY backend/go.mod backend/go.sum ./ RUN go mod download -COPY *.go ./ -COPY migrations/ ./migrations/ +COPY backend/*.go ./ +COPY backend/migrations/ ./migrations/ RUN CGO_ENABLED=0 go build -ldflags "-X main.version=$(git rev-parse --short HEAD)" -o dmrmap . FROM alpine:3.19 WORKDIR /app COPY --from=builder /build/dmrmap . COPY --from=builder /build/migrations/ ./migrations/ -COPY static/ ./static/ +COPY frontend/static/ ./static/ COPY --from=frontend /build/static/app.js ./static/app.js -COPY rptrs.json . -COPY bmrptrs.json . +COPY backend/data/rptrs.json . +COPY backend/data/bmrptrs.json . RUN wget -qO static/talkgroups.json https://api.brandmeister.network/v2/talkgroup EXPOSE 8080 CMD ["./dmrmap"] diff --git a/Dockerfile.dev b/Dockerfile.dev index 92e8cc2..3a48c17 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -3,6 +3,6 @@ RUN apk add --no-cache nodejs npm RUN go install github.com/air-verse/air@latest RUN wget -qO /usr/local/share/talkgroups.json https://api.brandmeister.network/v2/talkgroup WORKDIR /app -CMD cp -n /usr/local/share/talkgroups.json static/talkgroups.json 2>/dev/null; \ - npm install --silent && npm run watch & \ +CMD cp -n /usr/local/share/talkgroups.json frontend/static/talkgroups.json 2>/dev/null; \ + cd frontend && npm install --silent && npm run watch & \ air diff --git a/admin.go b/backend/admin.go similarity index 98% rename from admin.go rename to backend/admin.go index e951a66..9f3646e 100644 --- a/admin.go +++ b/backend/admin.go @@ -7,6 +7,7 @@ import ( "log" "net/http" "net/url" + "path/filepath" "strconv" "strings" "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) { - http.ServeFile(w, r, "static/admin.html") + http.ServeFile(w, r, adminPath) } } diff --git a/bmdevice.go b/backend/bmdevice.go similarity index 100% rename from bmdevice.go rename to backend/bmdevice.go diff --git a/bmrptrs.json b/backend/data/bmrptrs.json similarity index 100% rename from bmrptrs.json rename to backend/data/bmrptrs.json diff --git a/rptrs.json b/backend/data/rptrs.json similarity index 100% rename from rptrs.json rename to backend/data/rptrs.json diff --git a/db.go b/backend/db.go similarity index 100% rename from db.go rename to backend/db.go diff --git a/go.mod b/backend/go.mod similarity index 100% rename from go.mod rename to backend/go.mod diff --git a/go.sum b/backend/go.sum similarity index 100% rename from go.sum rename to backend/go.sum diff --git a/handlers.go b/backend/handlers.go similarity index 100% rename from handlers.go rename to backend/handlers.go diff --git a/main.go b/backend/main.go similarity index 89% rename from main.go rename to backend/main.go index df1c856..b026770 100644 --- a/main.go +++ b/backend/main.go @@ -13,6 +13,8 @@ func main() { jsonPath := envOr("JSON_PATH", "rptrs.json") bmrptrsPath := envOr("BMRPTRS_PATH", "bmrptrs.json") addr := envOr("LISTEN_ADDR", ":8080") + staticDir := envOr("STATIC_DIR", "static") + migrationsDir := envOr("MIGRATIONS_DIR", "migrations") db, err := openDB(dsn) if err != nil { @@ -20,7 +22,7 @@ func main() { } defer db.Close() - if err := runMigrations(db); err != nil { + if err := runMigrations(db, migrationsDir); err != nil { log.Fatalf("Failed to run migrations: %v", err) } @@ -43,7 +45,7 @@ func main() { mux.HandleFunc("/api/version", handleVersion()) if adminToken := os.Getenv("ADMIN_TOKEN"); adminToken != "" { - mux.HandleFunc("/admin/", handleAdminPage()) + mux.HandleFunc("/admin/", handleAdminPage(staticDir)) adminAPI := http.NewServeMux() adminAPI.HandleFunc("/admin/api/repeaters", handleAdminRepeaters(db)) adminAPI.HandleFunc("/admin/api/repeaters/update", handleAdminUpdateRepeater(db)) @@ -55,7 +57,7 @@ func main() { 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.Fatal(http.ListenAndServe(addr, mux)) diff --git a/migrate.go b/backend/migrate.go similarity index 71% rename from migrate.go rename to backend/migrate.go index 0477aac..1ae5fda 100644 --- a/migrate.go +++ b/backend/migrate.go @@ -7,11 +7,11 @@ import ( "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 { return err } - if err := goose.Up(db, "migrations"); err != nil { + if err := goose.Up(db, dir); err != nil { return err } log.Println("Database migrations applied successfully") diff --git a/migrations/001_initial_schema.sql b/backend/migrations/001_initial_schema.sql similarity index 100% rename from migrations/001_initial_schema.sql rename to backend/migrations/001_initial_schema.sql diff --git a/migrations/002_add_bm_device_fields.sql b/backend/migrations/002_add_bm_device_fields.sql similarity index 100% rename from migrations/002_add_bm_device_fields.sql rename to backend/migrations/002_add_bm_device_fields.sql diff --git a/migrations/003_networks_array.sql b/backend/migrations/003_networks_array.sql similarity index 100% rename from migrations/003_networks_array.sql rename to backend/migrations/003_networks_array.sql diff --git a/migrations/005_changelog.sql b/backend/migrations/005_changelog.sql similarity index 100% rename from migrations/005_changelog.sql rename to backend/migrations/005_changelog.sql diff --git a/seed.go b/backend/seed.go similarity index 100% rename from seed.go rename to backend/seed.go diff --git a/compose.dev.yml b/compose.dev.yml index c68d55f..715e20a 100644 --- a/compose.dev.yml +++ b/compose.dev.yml @@ -20,15 +20,17 @@ services: - .:/app - go-mod-cache:/go/pkg/mod - go-build-cache:/root/.cache/go-build - - node_modules:/app/node_modules + - node_modules:/app/frontend/node_modules depends_on: - postgres environment: - DATABASE_URL=postgres://dmrmap:dmrmap@postgres:5432/dmrmap?sslmode=disable - - JSON_PATH=/app/rptrs.json - - BMRPTRS_PATH=/app/bmrptrs.json + - JSON_PATH=/app/backend/data/rptrs.json + - BMRPTRS_PATH=/app/backend/data/bmrptrs.json - LISTEN_ADDR=:8080 - ADMIN_TOKEN=adminparty + - STATIC_DIR=/app/frontend/static + - MIGRATIONS_DIR=/app/backend/migrations volumes: go-mod-cache: diff --git a/compose.test.yml b/compose.test.yml index dbeff31..ec04eb2 100644 --- a/compose.test.yml +++ b/compose.test.yml @@ -1,10 +1,10 @@ services: test: image: node:22-alpine - working_dir: /app + working_dir: /app/frontend volumes: - .:/app - - node_modules_test:/app/node_modules + - node_modules_test:/app/frontend/node_modules command: sh -c "npm install --silent && npm test" volumes: diff --git a/package-lock.json b/frontend/package-lock.json similarity index 100% rename from package-lock.json rename to frontend/package-lock.json diff --git a/package.json b/frontend/package.json similarity index 100% rename from package.json rename to frontend/package.json diff --git a/src/cps-anytone.test.ts b/frontend/src/cps-anytone.test.ts similarity index 100% rename from src/cps-anytone.test.ts rename to frontend/src/cps-anytone.test.ts diff --git a/src/cps-anytone.ts b/frontend/src/cps-anytone.ts similarity index 100% rename from src/cps-anytone.ts rename to frontend/src/cps-anytone.ts diff --git a/src/cps-motorola.test.ts b/frontend/src/cps-motorola.test.ts similarity index 100% rename from src/cps-motorola.test.ts rename to frontend/src/cps-motorola.test.ts diff --git a/src/cps-motorola.ts b/frontend/src/cps-motorola.ts similarity index 100% rename from src/cps-motorola.ts rename to frontend/src/cps-motorola.ts diff --git a/src/filters.test.ts b/frontend/src/filters.test.ts similarity index 100% rename from src/filters.test.ts rename to frontend/src/filters.test.ts diff --git a/src/filters.ts b/frontend/src/filters.ts similarity index 100% rename from src/filters.ts rename to frontend/src/filters.ts diff --git a/src/format.test.ts b/frontend/src/format.test.ts similarity index 100% rename from src/format.test.ts rename to frontend/src/format.test.ts diff --git a/src/format.ts b/frontend/src/format.ts similarity index 100% rename from src/format.ts rename to frontend/src/format.ts diff --git a/src/geo.test.ts b/frontend/src/geo.test.ts similarity index 100% rename from src/geo.test.ts rename to frontend/src/geo.test.ts diff --git a/src/geo.ts b/frontend/src/geo.ts similarity index 100% rename from src/geo.ts rename to frontend/src/geo.ts diff --git a/src/globals.d.ts b/frontend/src/globals.d.ts similarity index 100% rename from src/globals.d.ts rename to frontend/src/globals.d.ts diff --git a/src/main.ts b/frontend/src/main.ts similarity index 100% rename from src/main.ts rename to frontend/src/main.ts diff --git a/src/popup.test.ts b/frontend/src/popup.test.ts similarity index 100% rename from src/popup.test.ts rename to frontend/src/popup.test.ts diff --git a/src/popup.ts b/frontend/src/popup.ts similarity index 100% rename from src/popup.ts rename to frontend/src/popup.ts diff --git a/src/talkgroups.test.ts b/frontend/src/talkgroups.test.ts similarity index 100% rename from src/talkgroups.test.ts rename to frontend/src/talkgroups.test.ts diff --git a/src/talkgroups.ts b/frontend/src/talkgroups.ts similarity index 100% rename from src/talkgroups.ts rename to frontend/src/talkgroups.ts diff --git a/src/types.ts b/frontend/src/types.ts similarity index 100% rename from src/types.ts rename to frontend/src/types.ts diff --git a/static/admin.html b/frontend/static/admin.html similarity index 100% rename from static/admin.html rename to frontend/static/admin.html diff --git a/static/datenschutz.html b/frontend/static/datenschutz.html similarity index 100% rename from static/datenschutz.html rename to frontend/static/datenschutz.html diff --git a/static/i18n.js b/frontend/static/i18n.js similarity index 100% rename from static/i18n.js rename to frontend/static/i18n.js diff --git a/static/impressum.html b/frontend/static/impressum.html similarity index 100% rename from static/impressum.html rename to frontend/static/impressum.html diff --git a/static/index.html b/frontend/static/index.html similarity index 100% rename from static/index.html rename to frontend/static/index.html diff --git a/static/lib/i18next-browser-languagedetector.min.js b/frontend/static/lib/i18next-browser-languagedetector.min.js similarity index 100% rename from static/lib/i18next-browser-languagedetector.min.js rename to frontend/static/lib/i18next-browser-languagedetector.min.js diff --git a/static/lib/i18next-http-backend.min.js b/frontend/static/lib/i18next-http-backend.min.js similarity index 100% rename from static/lib/i18next-http-backend.min.js rename to frontend/static/lib/i18next-http-backend.min.js diff --git a/static/lib/i18next.min.js b/frontend/static/lib/i18next.min.js similarity index 100% rename from static/lib/i18next.min.js rename to frontend/static/lib/i18next.min.js diff --git a/static/lib/images/marker-icon-2x.png b/frontend/static/lib/images/marker-icon-2x.png similarity index 100% rename from static/lib/images/marker-icon-2x.png rename to frontend/static/lib/images/marker-icon-2x.png diff --git a/static/lib/images/marker-icon.png b/frontend/static/lib/images/marker-icon.png similarity index 100% rename from static/lib/images/marker-icon.png rename to frontend/static/lib/images/marker-icon.png diff --git a/static/lib/images/marker-shadow.png b/frontend/static/lib/images/marker-shadow.png similarity index 100% rename from static/lib/images/marker-shadow.png rename to frontend/static/lib/images/marker-shadow.png diff --git a/static/lib/leaflet.css b/frontend/static/lib/leaflet.css similarity index 100% rename from static/lib/leaflet.css rename to frontend/static/lib/leaflet.css diff --git a/static/lib/leaflet.js b/frontend/static/lib/leaflet.js similarity index 100% rename from static/lib/leaflet.js rename to frontend/static/lib/leaflet.js diff --git a/static/lib/socket.io.min.js b/frontend/static/lib/socket.io.min.js similarity index 100% rename from static/lib/socket.io.min.js rename to frontend/static/lib/socket.io.min.js diff --git a/static/locales/de.json b/frontend/static/locales/de.json similarity index 100% rename from static/locales/de.json rename to frontend/static/locales/de.json diff --git a/static/locales/en.json b/frontend/static/locales/en.json similarity index 100% rename from static/locales/en.json rename to frontend/static/locales/en.json diff --git a/static/locales/es.json b/frontend/static/locales/es.json similarity index 100% rename from static/locales/es.json rename to frontend/static/locales/es.json diff --git a/static/locales/fr.json b/frontend/static/locales/fr.json similarity index 100% rename from static/locales/fr.json rename to frontend/static/locales/fr.json diff --git a/static/locales/it.json b/frontend/static/locales/it.json similarity index 100% rename from static/locales/it.json rename to frontend/static/locales/it.json diff --git a/static/locales/pl.json b/frontend/static/locales/pl.json similarity index 100% rename from static/locales/pl.json rename to frontend/static/locales/pl.json diff --git a/static/style.css b/frontend/static/style.css similarity index 100% rename from static/style.css rename to frontend/static/style.css diff --git a/tsconfig.json b/frontend/tsconfig.json similarity index 100% rename from tsconfig.json rename to frontend/tsconfig.json diff --git a/vitest.config.ts b/frontend/vitest.config.ts similarity index 100% rename from vitest.config.ts rename to frontend/vitest.config.ts