From a05011396ffa7024e929cfd91ffa1942b393e76a Mon Sep 17 00:00:00 2001 From: c0dev0id Date: Mon, 23 Mar 2026 19:38:22 +0100 Subject: [PATCH] add mapforge: web-based GIS vector editor Ruby on Rails 8.1 app backed by MongoDB and Redis. Git snapshot from 2026-03-22 (no upstream releases yet). Requires Ruby 4.0, libproj (rgeo-proj4 C ext), and ImageMagick (rszr C ext). --- geo/mapforge/CLAUDE.md | 105 +++++++++++++++++++++++++++++++++ geo/mapforge/Makefile | 78 ++++++++++++++++++++++++ geo/mapforge/distinfo | 2 + geo/mapforge/files/mapforge.rc | 21 +++++++ geo/mapforge/pkg/DESCR | 9 +++ geo/mapforge/pkg/PLIST | 6 ++ 6 files changed, 221 insertions(+) create mode 100644 geo/mapforge/CLAUDE.md create mode 100644 geo/mapforge/Makefile create mode 100644 geo/mapforge/distinfo create mode 100644 geo/mapforge/files/mapforge.rc create mode 100644 geo/mapforge/pkg/DESCR create mode 100644 geo/mapforge/pkg/PLIST diff --git a/geo/mapforge/CLAUDE.md b/geo/mapforge/CLAUDE.md new file mode 100644 index 0000000..fc33c43 --- /dev/null +++ b/geo/mapforge/CLAUDE.md @@ -0,0 +1,105 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What this port is + +An OpenBSD port for [mapforge](https://github.com/mapforge-org/mapforge), a self-hosted web GIS application. It is a Ruby on Rails 8.1 app backed by MongoDB and Redis, with MapLibre GL JS on the frontend. + +- No upstream releases — the port tracks a git snapshot (`GIT_COMMIT` + `SNAP` in Makefile) +- To update to a newer commit: change `GIT_COMMIT` and `SNAP`, then run `doas make makesum` + +## Build commands + +```sh +doas make fetch # download source tarball from GitHub +doas make patch # extract and apply patches +doas make build # bundle install + bootsnap precompile +doas make fake # stage into WRKINST +doas make package # create the .tgz package +doas make install # install from package +doas make clean=all # full clean (use instead of make clean) +``` + +Run from `/usr/ports/mystuff/geo/mapforge/`. + +## Gem dependency handling + +This port has no cargo-style bundler module in OpenBSD ports infrastructure. Two approaches: + +**Development (network access):** `do-build` calls `bundle install` which fetches gems from rubygems.org and git. Requires network access during the build phase — acceptable for local development. + +**Proper offline build:** Pre-generate a vendor cache and add it as a distfile: + +```sh +# After make extract, in WRKDIST: +bundle _4.0.3_ config set --local without "development test" +bundle _4.0.3_ package --all --all-platforms --no-install +tar czf ${DISTDIR}/mapforge-gems-20260322.tar.gz vendor/cache/ +``` + +Then add `DISTFILES += mapforge-gems-${SNAP}.tar.gz` to the Makefile, extract it in `post-extract` into `${WRKSRC}/vendor/cache/`, and use `bundle install --local` in `do-build`. + +Two Gemfile entries use git sources (not rubygems.org): +- `gpx` from `https://github.com/digitaltom/gpx` (Ruby 4.0 fork) +- `net-pop` from `https://github.com/ruby/net-pop` + +These will be fetched by bundler during build. For a fully offline build, vendor them too via `bundle package --all`. + +## Ruby version + +Tied to Ruby 4.0 (`MODRUBY_REV = 4.0`). The Gemfile enforces `ruby "4.0.0"` and the Gemfile.lock was generated with bundler 4.0.3 (built into Ruby 4.0). + +Relevant paths once ruby40 is installed: +- `${LOCALBASE}/bin/ruby40` +- `${LOCALBASE}/bin/bundle40` +- `${LOCALBASE}/bin/gem40` + +## C extension gems + +Three gems compile native extensions at `bundle install` time: +- **rgeo** — geospatial types; optionally links against GEOS (not required) +- **rgeo-proj4** — coordinate projections; links against `libproj` (`devel/proj`) +- **rszr** — image resizing; links against `MagickCore-6.Q16`, `MagickWand-6.Q16` (`graphics/ImageMagick`) + +This makes the package architecture-dependent (no `PKG_ARCH=*`). + +## Runtime services + +The app needs these running before starting: +- `mongod` from `databases/mongodb/80` +- `redis-server` from `databases/redis` + +Start with `rcctl start mongod redis mapforge`. + +## Installation layout + +| Path | Contents | +|---|---| +| `${PREFIX}/share/mapforge/` | Application code + vendored gems | +| `${LOCALSTATEDIR}/mapforge/log/` | Rails logs | +| `${LOCALSTATEDIR}/mapforge/storage/` | Active Storage uploads | +| `${LOCALSTATEDIR}/mapforge/tmp/` | Pids, sockets, cache | +| `${PREFIX}/share/examples/mapforge/mapforge.rc` | rc.d startup script template | + +Copy `mapforge.rc` to `/etc/rc.d/mapforge` and enable with `rcctl enable mapforge`. + +## Environment variables + +Required in production: +- `SECRET_KEY_BASE` — Rails secret (generate with `bundle exec rails secret`) +- `RAILS_ENV=production` + +Optional OAuth login: +- `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET` +- `GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET` +- `OSM_CLIENT_ID` / `OSM_CLIENT_SECRET` + +## PLIST + +The PLIST placeholder needs to be replaced after a successful build: + +```sh +doas make fake +doas make update-plist +``` diff --git a/geo/mapforge/Makefile b/geo/mapforge/Makefile new file mode 100644 index 0000000..04a9dd0 --- /dev/null +++ b/geo/mapforge/Makefile @@ -0,0 +1,78 @@ +COMMENT = open source web-based GIS vector editor + +# No upstream releases; pin to a git snapshot +GIT_COMMIT = 0c0e1387da1910a2a3b60c6d7c48d0552c701a3c +SNAP = 20260322 +PKGNAME = mapforge-0.${SNAP} + +DIST_TUPLE = github mapforge-org mapforge ${GIT_COMMIT} . + +CATEGORIES = geo www + +HOMEPAGE = https://github.com/mapforge-org/mapforge + +# AGPLv3 (source), MPL-2.0 (vendor/javascript) +PERMIT_PACKAGE = Yes + +MODULES = lang/ruby +MODRUBY_REV = 4.0 +MODRUBY_HANDLE_FLAVORS = No + +BUNDLE = ${LOCALBASE}/bin/bundle${MODRUBY_BINREV} + +CONFIGURE_STYLE = none +NO_TEST = Yes + +# C extensions (rgeo, rgeo-proj4, rszr) make the package arch-dependent +COMPILER = base-clang ports-gcc +COMPILER_LANGS = c + +# git-sourced gems in Gemfile require git at bundle-install time +BUILD_DEPENDS += devel/git + +# rgeo-proj4 C extension links against libproj +LIB_DEPENDS += devel/proj +# rszr C extension links against ImageMagick +LIB_DEPENDS += graphics/ImageMagick + +WANTLIB += proj MagickCore-6.Q16 MagickWand-6.Q16 + +# mongod and redis servers are needed at runtime +RUN_DEPENDS += databases/mongodb/80 \ + databases/redis + +APP_DIR = ${PREFIX}/share/mapforge +DATA_DIR = ${LOCALSTATEDIR}/mapforge + +SUBST_VARS += APP_DIR DATA_DIR MODRUBY_BINREV + +# --- Gem vendor cache --- +# The gem vendor cache must be pre-generated and added as a distfile +# before this port can build offline. Steps after "make extract": +# +# cd ${WRKDIST} +# bundle _4.0.3_ config set --local without "development test" +# bundle _4.0.3_ package --all --all-platforms --no-install +# tar czf ${DISTDIR}/mapforge-gems-${SNAP}.tar.gz vendor/cache/ +# +# Then add to DISTFILES and re-run "make makesum". Until the cache +# is generated, bundle install will fetch gems from rubygems.org. + +do-build: + cd ${WRKSRC} && \ + ${BUNDLE} config set --local without "development test" && \ + ${BUNDLE} config set --local deployment true && \ + ${BUNDLE} install && \ + ${RUBY} ./bin/bootsnap precompile --gemfile app/ lib/ + +do-install: + ${INSTALL_DATA_DIR} ${WRKINST}${APP_DIR} + cd ${WRKSRC} && pax -rw . ${WRKINST}${APP_DIR}/ + ${INSTALL_DATA_DIR} ${WRKINST}${DATA_DIR}/log + ${INSTALL_DATA_DIR} ${WRKINST}${DATA_DIR}/storage + ${INSTALL_DATA_DIR} ${WRKINST}${DATA_DIR}/tmp + ${INSTALL_DATA_DIR} ${WRKINST}${PREFIX}/share/examples/mapforge + ${INSTALL_SCRIPT} ${FILESDIR}/mapforge.rc \ + ${WRKINST}${PREFIX}/share/examples/mapforge/ + +.include diff --git a/geo/mapforge/distinfo b/geo/mapforge/distinfo new file mode 100644 index 0000000..a0b56e2 --- /dev/null +++ b/geo/mapforge/distinfo @@ -0,0 +1,2 @@ +SHA256 (mapforge-org-mapforge-0c0e1387da1910a2a3b60c6d7c48d0552c701a3c.tar.gz) = O8aIwFOQBQH7Q/TcjeEreD4GYqcSMreXQKTmsXphWCc= +SIZE (mapforge-org-mapforge-0c0e1387da1910a2a3b60c6d7c48d0552c701a3c.tar.gz) = 50532678 diff --git a/geo/mapforge/files/mapforge.rc b/geo/mapforge/files/mapforge.rc new file mode 100644 index 0000000..0955d2f --- /dev/null +++ b/geo/mapforge/files/mapforge.rc @@ -0,0 +1,21 @@ +#!/bin/ksh + +daemon="${TRUEPREFIX}/share/mapforge/bin/thrust" +daemon_user="_mapforge" +daemon_flags="" + +pexp="ruby${MODRUBY_BINREV}.*puma" + +. /etc/rc.d/rc.subr + +rc_bg=YES +rc_reload=NO + +rc_pre() { + export RAILS_ENV=production + export RAILS_LOG_TO_STDOUT=true + export BUNDLE_PATH="${TRUEPREFIX}/share/mapforge/vendor/bundle" + cd "${TRUEPREFIX}/share/mapforge" || exit 1 +} + +rc_cmd $1 diff --git a/geo/mapforge/pkg/DESCR b/geo/mapforge/pkg/DESCR new file mode 100644 index 0000000..5c8c39d --- /dev/null +++ b/geo/mapforge/pkg/DESCR @@ -0,0 +1,9 @@ +Mapforge is a self-hosted web-based GIS application for creating and sharing +geospatial data collaboratively. Users can draw shapes, import GeoJSON/GPX/KML +files, query OpenStreetMap via the Overpass API, and edit maps together in +real time using WebSockets. + +The frontend uses MapLibre GL JS with Stimulus/Hotwire. The backend is a Ruby +on Rails application using MongoDB for storage and Redis for caching and +real-time synchronisation. Optionally supports GitHub, Google, and +OpenStreetMap OAuth2 login. diff --git a/geo/mapforge/pkg/PLIST b/geo/mapforge/pkg/PLIST new file mode 100644 index 0000000..3181bd3 --- /dev/null +++ b/geo/mapforge/pkg/PLIST @@ -0,0 +1,6 @@ +@comment TODO: run "make update-plist" after a successful build to generate this file +@dir ${APP_DIR} +@dir ${DATA_DIR}/log +@dir ${DATA_DIR}/storage +@dir ${DATA_DIR}/tmp +share/examples/mapforge/mapforge.rc