diff --git a/README.md b/README.md index c09746e..dbd3919 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ bash init.sh | `just julia` | Install Julia via juliaup | | `just haskell` | Install Haskell via ghcup | | `just python` | Install uv (Python package manager) | +| `just node` | Install fnm (Node version manager) with Node LTS and enable pnpm via corepack | | `just go` / `just go update` | Install or update Go | | `just neovim` / `just neovim update` | Install or update Neovim (pass `home` to install under `~/.local`) | | `just emacs` / `just emacs update` | Install or update Emacs (system build is pgtk, home build is nox) | diff --git a/scripts/install-node.sh b/scripts/install-node.sh new file mode 100644 index 0000000..457e5d6 --- /dev/null +++ b/scripts/install-node.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +set -euo pipefail + +# fnm's install is OS-uniform (curl | bash), so no arg is needed. + +# fnm (Fast Node Manager) +# --skip-shell: the installer aborts with "Could not infer shell" when $SHELL is +# unset (CI / non-interactive). Persistent shell integration lives statically in the +# repo-tracked rc files (settings-bash/.bashrc, settings-zsh/.zshrc). +if ! command -v fnm &>/dev/null; then + curl -fsSL https://fnm.vercel.app/install | bash -s -- --skip-shell +fi + +# On Linux the installer drops fnm in ~/.local/share/fnm; on mac it uses Homebrew, +# which is already on PATH (this prepend is then a harmless no-op). +export PATH="$HOME/.local/share/fnm:$PATH" +# --shell bash: this script always runs under bash (shebang + `bash ...` in the +# recipe), and fnm's process-tree shell detection is unreliable in CI +# (su -l ci -c ... just), emitting nothing so a later `fnm use` aborts with +# "We can't find the necessary environment variables". Forcing the shell is safe +# regardless of the user's interactive shell. +eval "$(fnm env --shell bash)" + +# Already fully set up (fnm present with Node + pnpm) — nothing to do. +if command -v pnpm &>/dev/null; then + echo "fnm and pnpm are already installed" + fnm --version + node --version + pnpm --version + exit 0 +fi + +# Node LTS provides corepack, which provides pnpm +fnm install --lts +fnm use lts-latest +fnm default lts-latest + +# Enable pnpm shim via corepack +corepack enable pnpm + +fnm --version +node --version +pnpm --version diff --git a/settings-bash/.bashrc b/settings-bash/.bashrc index 75cab1e..e836afb 100644 --- a/settings-bash/.bashrc +++ b/settings-bash/.bashrc @@ -172,6 +172,10 @@ case ":$PATH:" in ;; esac +# fnm (Node version manager) +export PATH="$HOME/.local/share/fnm:$PATH" +command -v fnm >/dev/null && eval "$(fnm env --use-on-cd)" + # ble.sh attach and keybindings if [[ ${BLE_VERSION-} ]]; then ble-bind -m auto_complete -f 'S-TAB' auto_complete/insert diff --git a/settings-zsh/.zshrc b/settings-zsh/.zshrc index 6c82a6c..769ba59 100644 --- a/settings-zsh/.zshrc +++ b/settings-zsh/.zshrc @@ -79,6 +79,10 @@ export PATH # <<< juliaup initialize <<< +# fnm (Node version manager) +export PATH="$HOME/.local/share/fnm:$PATH" +command -v fnm >/dev/null && eval "$(fnm env --use-on-cd)" + [ -f "$HOME/.ghcup/env" ] && source "$HOME/.ghcup/env" # ghcup-envexport PYENV_ROOT="$HOME/.pyenv" [[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init -)"