aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/meshbay-client/build/installer.nsh38
-rw-r--r--packages/meshbay-node/tests/test_packaging_win.py22
-rw-r--r--packaging/win/README.md6
3 files changed, 61 insertions, 5 deletions
diff --git a/packages/meshbay-client/build/installer.nsh b/packages/meshbay-client/build/installer.nsh
index cf8e5ff..15a840f 100644
--- a/packages/meshbay-client/build/installer.nsh
+++ b/packages/meshbay-client/build/installer.nsh
@@ -1,22 +1,50 @@
; electron-builder NSIS customisation (auto-included: build/installer.nsh).
;
-; Per-user install, no elevation (package.json build.nsis). These macros only
-; deal with the one piece of state that lives outside the install directory:
-; the W3 "run at sign-in" launcher the node's own CLI can create.
+; Per-user install, no elevation (package.json build.nsis). This does two things
+; beyond the default: put the bundled daemon on the user's PATH so `meshbay-node`
+; works in a terminal, and clean up the one piece of state that lives outside
+; the install directory (the W3 "run at sign-in" launcher).
;
-; Deliberately NOT touched here:
+; Deliberately NOT touched:
; - %LOCALAPPDATA%\meshbay\ (node.toml, keystore.enc, unlock.key, data/) --
; the keystore must survive an uninstall/reinstall; installers place files,
; never remove secrets.
+!include "WinMessages.nsh"
+!include "WordFunc.nsh"
+!insertmacro WordAdd
+!insertmacro un.WordAdd
+
+; The dir electron-builder drops resources into. `meshbay-node.exe` and its
+; frozen Python live directly in here. A fixed suffix of $INSTDIR, so both the
+; add (install) and the remove (uninstall, where $INSTDIR is still known) match
+; the exact same string.
+!define MB_NODE_BIN "$INSTDIR\resources\node-runtime"
+
!macro customInstall
- ; resources\node-runtime\meshbay-node.exe is overwritten by this install; a
+ ; resources\node-runtime\meshbay-node.exe is about to be overwritten; a
; daemon still running from a previous version holds the file open.
nsExec::Exec 'taskkill /IM meshbay-node.exe /F'
+
+ ; Add the daemon dir to the per-user PATH (HKCU\Environment). WordAdd is a
+ ; stock NSIS macro over a ';'-delimited list -- it is a no-op if the entry is
+ ; already there, so a reinstall does not double it. New shells only; the
+ ; broadcast tells already-open Explorer/shells to reload the environment.
+ ReadRegStr $0 HKCU "Environment" "Path"
+ ${WordAdd} "$0" ";" "+${MB_NODE_BIN}" $1
+ WriteRegExpandStr HKCU "Environment" "Path" "$1"
+ SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
!macroend
!macro customUnInstall
nsExec::Exec 'taskkill /IM meshbay-node.exe /F'
+
+ ; Take our entry back out of PATH, leaving the rest of it alone.
+ ReadRegStr $0 HKCU "Environment" "Path"
+ ${un.WordAdd} "$0" ";" "-${MB_NODE_BIN}" $1
+ WriteRegExpandStr HKCU "Environment" "Path" "$1"
+ SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
+
; meshbay_node.platform._startup_vbs() -- if the user ran "meshbay-node
; autostart install" (or toggled it in the client), this points wscript at
; the binary we are about to delete, and would error at every sign-in.
diff --git a/packages/meshbay-node/tests/test_packaging_win.py b/packages/meshbay-node/tests/test_packaging_win.py
index 1b7521a..8c8e272 100644
--- a/packages/meshbay-node/tests/test_packaging_win.py
+++ b/packages/meshbay-node/tests/test_packaging_win.py
@@ -151,3 +151,25 @@ def test_customInstall_stops_a_running_daemon_before_overwriting_it():
nsh = NSH.read_text(encoding="utf-8")
body = nsh.split("!macro customInstall", 1)[1].split("!macroend", 1)[0]
assert "taskkill /IM meshbay-node.exe /F" in body
+
+
+def test_the_bundled_daemon_goes_on_the_user_path_and_comes_back_off():
+ """
+ The installer has no console entry point of its own; without this the
+ operator has to `cd` into resources\\node-runtime\\ to run `meshbay-node`.
+ The add uses stock WordFunc (no EnVar plugin — electron-builder's NSIS does
+ not bundle it) and the same $INSTDIR-relative string on the way out.
+ """
+ nsh = NSH.read_text(encoding="utf-8")
+ assert "!insertmacro WordAdd" in nsh and "!insertmacro un.WordAdd" in nsh
+
+ install = nsh.split("!macro customInstall", 1)[1].split("!macroend", 1)[0]
+ uninstall = nsh.split("!macro customUnInstall", 1)[1].split("!macroend", 1)[0]
+ assert 'HKCU "Environment" "Path"' in install
+ assert "${WordAdd}" in install and '"+${MB_NODE_BIN}"' in install
+ assert "${un.WordAdd}" in uninstall and '"-${MB_NODE_BIN}"' in uninstall
+ # New shells need the broadcast to notice.
+ assert "WM_WININICHANGE" in install and "WM_WININICHANGE" in uninstall
+ # PATH points at the real .exe dir, so `where meshbay-node` resolves to the
+ # binary the client and the W3 launcher use too — not a shim.
+ assert 'MB_NODE_BIN "$INSTDIR\\resources\\node-runtime"' in nsh
diff --git a/packaging/win/README.md b/packaging/win/README.md
index d02adca..0ba18ca 100644
--- a/packaging/win/README.md
+++ b/packaging/win/README.md
@@ -22,6 +22,12 @@ Runtime data stays where the node already puts it: `%LOCALAPPDATA%\meshbay\`
(`node.toml`, `keystore.enc`, `unlock.key`, `data\`). The installer never writes
there and the uninstaller never deletes it — installers place files, not secrets.
+`build/installer.nsh` also adds `…\resources\node-runtime` to the **per-user**
+`Path` (`HKCU\Environment`) so `meshbay-node` works in a terminal, and takes it
+back out on uninstall. New shells only — a `WM_SETTINGCHANGE` broadcast nudges
+open ones. It uses stock `WordFunc.nsh` (the `EnVar` plugin is not in
+electron-builder's NSIS bundle).
+
## Build
On a Windows machine with **Node ≥ 22**, **Python ≥ 3.12** (`py -3.12`) and