clawdie-iso/firstboot/shell-npm-globals.sh

103 lines
3.8 KiB
Bash
Executable file

#!/bin/sh
# Clawdie Shell — NPM Globals Module
# Purpose: Install bundled npm-global CLI tools (currently pi only)
# from local tarballs shipped on the install media. Fully offline.
# POSIX-compliant (no bash-isms)
#
# Runs after shell-pkg.sh (so node24 + npm exist) and before shell-deploy.sh
# (so the agent runtime can find `pi` on PATH at first run).
set -eu
# Configuration (can be overridden for testing)
SHARE="${SHARE:-/usr/local/share/clawdie-iso}"
NPM_GLOBALS_DIR="${NPM_GLOBALS_DIR:-${SHARE}/npm-globals}"
CLAWDIE_HOME="${CLAWDIE_HOME:-/home/clawdie}"
# MUST match shell-system.sh's /etc/profile.d/clawdie.sh which sets:
# export npm_config_prefix="/opt/clawdie/npm-global"
# export PATH="/opt/clawdie/npm-global/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${PATH}"
# Otherwise globals land in /usr/local/bin and the clawdie user's PATH
# (and the agent runtime's commandExists() probes) won't find them.
NPM_PREFIX="${NPM_PREFIX:-/opt/clawdie/npm-global}"
LOG_FILE="${LOG_FILE:-/var/log/clawdie-firstboot.log}"
PROGRESS_FILE="${PROGRESS_FILE:-/var/log/clawdie-firstboot.progress}"
# ============================================================================
# MAIN ENTRY POINT
# ============================================================================
clawdie_shell_npm_globals_install() {
log_msg "[npm-globals] Starting offline install of bundled npm CLIs"
if ! command -v npm >/dev/null 2>&1; then
log_msg "[npm-globals] ERROR: npm not found in PATH"
return 1
fi
if [ ! -d "$NPM_GLOBALS_DIR" ]; then
log_msg "[npm-globals] WARNING: $NPM_GLOBALS_DIR not present — skipping"
echo "[NPM-GLOBALS] SKIPPED" >> "$PROGRESS_FILE"
return 0
fi
# Ensure target prefix exists and is owned by clawdie. Aligns with
# shell-system.sh's /etc/profile.d/clawdie.sh PATH setup.
mkdir -p "$NPM_PREFIX/bin" "$NPM_PREFIX/lib"
if id clawdie >/dev/null 2>&1; then
chown -R clawdie:clawdie "$NPM_PREFIX" 2>/dev/null || true
fi
# Keep the legacy path as a symlink for compatibility.
if [ ! -L "${CLAWDIE_HOME}/.npm-global" ]; then
rm -rf "${CLAWDIE_HOME}/.npm-global" 2>/dev/null || true
ln -s "$NPM_PREFIX" "${CLAWDIE_HOME}/.npm-global" 2>/dev/null || true
chown -h clawdie:clawdie "${CLAWDIE_HOME}/.npm-global" 2>/dev/null || true
fi
_found=0
for tgz in "$NPM_GLOBALS_DIR"/*.tgz; do
[ -f "$tgz" ] || continue
_found=1
log_msg "[npm-globals] Installing $(basename "$tgz")$NPM_PREFIX"
# Run as clawdie user with the same env the login shell will see,
# so binaries land in /opt/clawdie/npm-global/bin/.
if id clawdie >/dev/null 2>&1 && [ "$(id -u)" -eq 0 ]; then
if su - clawdie -c "npm_config_prefix='$NPM_PREFIX' npm install -g '$tgz'" >>"$LOG_FILE" 2>&1; then
log_msg "[npm-globals] ✓ $(basename "$tgz")"
else
log_msg "[npm-globals] ✗ FAILED: $(basename "$tgz")"
return 1
fi
else
if npm_config_prefix="$NPM_PREFIX" npm install -g "$tgz" >>"$LOG_FILE" 2>&1; then
log_msg "[npm-globals] ✓ $(basename "$tgz")"
else
log_msg "[npm-globals] ✗ FAILED: $(basename "$tgz")"
return 1
fi
fi
done
if [ "$_found" -eq 0 ]; then
log_msg "[npm-globals] WARNING: No .tgz files in $NPM_GLOBALS_DIR"
echo "[NPM-GLOBALS] SKIPPED" >> "$PROGRESS_FILE"
return 0
fi
echo "[NPM-GLOBALS] SUCCESS" >> "$PROGRESS_FILE"
log_msg "[npm-globals] Install complete"
return 0
}
# ============================================================================
# LOGGING HELPER
# ============================================================================
log_msg() {
echo "$(date '+%H:%M:%S') $1" | tee -a "$LOG_FILE" 2>/dev/null || true
}
# Only run if sourced directly (not during test, not from firstboot.sh)
if [ "${SHELL_NPM_GLOBALS_TEST:-0}" -eq 0 ]; then
clawdie_shell_npm_globals_install
fi