port the JS runtimes: node, bun and pm2 installed rather than offered

Not a choice. Officer does not run without them, so asking would be asking
whether to install Officer — which was settled by running the script. They are
installed and reported, with the reason each is load-bearing stated once:

  node  pm2 is a Node application, and officer-pty compiles node-pty against
        whatever Node is installed. There is no Linux prebuild, so this is not
        an ABI question — it is a build dependency on every machine.
  bun   the platform itself and nineteen of the twenty pm2 apps.
  pm2   supervises all of them, and the ecosystem files are written for it.

Node now tracks the current LTS, asked of nodejs.org, rather than the pinned
setup_22.x the original used — which ages into "the version we happened to pick"
the moment a new LTS lands. Resolves to v24.19.0 (Krypton) today, and NodeSource
publishes setup_24.x, checked with a HEAD request before anything is piped into a
shell.

Deno is the one genuine choice and stays optional, defaulting to no. Nothing in
Officer imports it — verified across the whole tree, the only references left are
in the old setup script — so the prompt says that outright and offers it for the
user's own work rather than pretending it is part of the platform.

bun is installed as the account and then symlinked into /usr/local/bin. pm2
started at boot by systemd has no login shell and therefore no ~/.bun/bin on
PATH; without the symlink every bun-based sidecar fails on reboot and works when
started by hand, which is a miserable thing to debug.

Every install is verified after it runs rather than trusting an exit status. A
NodeSource run can succeed while apt holds an older nodejs back, and reporting
the version asked for instead of the one present is how a machine ends up
disagreeing with its own setup log. Tested with an installer stubbed to succeed
and change nothing: both report failure.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-12 21:08:41 +00:00
co-authored by Claude Opus 5
parent 999362948f
commit 00e58931ff
2 changed files with 170 additions and 1 deletions
+100 -1
View File
@@ -1949,13 +1949,112 @@ if ! skip; then
step_ok
fi
# =============================================================================
# 25. JavaScript runtimes
# =============================================================================
#
# Not offered as a choice. Officer does not run without these, so asking would be
# asking whether to install Officer — which was settled by running this script.
# Deno is the exception and is asked, because nothing uses it.
step "JavaScript runtimes"
if ! skip; then
NODE_LTS="$(node_lts_major)"
NODE_NOW="$(node_installed_major)"
echo ""
info "JavaScript runtimes — required, so these are installed rather than offered"
echo " node ${NODE_NOW:+v$NODE_NOW }${NODE_NOW:+-> }LTS $(node_lts_label)"
echo " pm2 is a Node application, and officer-pty compiles node-pty"
echo " against whatever Node is installed — there is no Linux prebuild."
echo " bun $(bun_installed && bun --version 2>/dev/null || echo 'not installed')"
echo " the platform itself, and nineteen of the twenty pm2 apps."
echo " pm2 $(pm2_installed && echo installed || echo 'not installed')"
echo " supervises all of them, and the ecosystem files are written for it."
echo ""
# ── node ──
if [[ -z "$NODE_LTS" ]]; then
warn "could not reach nodejs.org to find the current LTS — leaving Node alone"
ERRORS+=("Node: could not determine the current LTS")
elif [[ "$NODE_NOW" == "$NODE_LTS" ]]; then
ok "node v${NODE_NOW} is the current LTS"
else
info " installing Node ${NODE_LTS}${NODE_NOW:+, replacing v$NODE_NOW}..."
# Checked afterwards rather than trusting the installer's exit status: a
# NodeSource run can succeed while apt keeps an older nodejs held back, and
# reporting the version we asked for instead of the one that is there is how
# a machine ends up disagreeing with its own setup log.
if install_node "$NODE_LTS" && [[ "$(node_installed_major)" == "$NODE_LTS" ]]; then
ok "node $(node -v)"
SUMMARY+=("Node: $(node -v) (current LTS)")
else
warn "the Node install did not complete"
ERRORS+=("Node: install failed")
fi
fi
# ── bun ──
if bun_installed; then
ok "bun $(bun --version 2>/dev/null) already installed"
else
info " installing bun..."
if install_bun && bun_installed; then
ok "bun $(bun --version), symlinked to /usr/local/bin/bun"
SUMMARY+=("Bun: $(bun --version)")
else
warn "the bun install did not complete"
ERRORS+=("Bun: install failed")
fi
fi
# ── pm2 ──
if pm2_installed; then
ok "pm2 $(pm2 -v 2>/dev/null | tail -1) already installed"
elif command -v npm &>/dev/null; then
info " installing pm2..."
if install_pm2 && pm2_installed; then
ok "pm2 $(pm2 -v | tail -1)"
SUMMARY+=("pm2: $(pm2 -v | tail -1)")
else
warn "the pm2 install did not complete"
ERRORS+=("pm2: install failed")
fi
else
warn "no npm, so pm2 cannot be installed — Node did not install correctly"
ERRORS+=("pm2: not installed, npm missing")
fi
# ── deno, which is the one genuine choice here ──
echo ""
if deno_installed; then
echo " deno is already installed — left alone"
else
info "Deno?"
echo " Nothing in Officer uses Deno. It was in the original setup script"
echo " for one thing that no longer exists, and there is no reference to"
echo " it anywhere in the platform today."
echo " Offered because you may want it for your own work."
if confirm "Install Deno?" n; then
if install_deno && deno_installed; then
ok "deno installed to ${USER_HOME}/.deno"
SUMMARY+=("Deno: installed (not used by Officer)")
else
warn "the Deno install did not complete"
fi
else
echo " skipped"
fi
fi
step_ok
fi
# =============================================================================
# NOT PORTED YET
# =============================================================================
#
# Sections still to move across from scripts/setup-old/setup-ubuntu.sh, in order:
#
# js runtimes ·
# dev tools · ufw · zshrc
#
# And one that is new rather than ported, to come last of all: