-
-
Save RichardTMiles/cf29cb157402e376f1d782b111583d38 to your computer and use it in GitHub Desktop.
NVM wrapper to make execution pass through the systems PATH bypassing the need for shell profile edits
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# --------------------------------------------------------------------------- | |
# nvx — self‑installing, self‑initialising, shell‑agnostic wrapper around nvm | |
# --------------------------------------------------------------------------- | |
# • Installs **nvm** (≥ $MIN_VERSION) the first time it runs. | |
# • Loads nvm with NVM_AUTO_MODE=install so `nvm use` auto‑installs versions. | |
# • Always activates an .nvmrc auto‑switch hook—no NVX_AUTO flag needed. | |
# • On first run it appends a single line to the user’s shell rc file: | |
# source /path/to/nvx | |
# so future shells initialise nvx automatically. | |
# • Safe to *execute* or *source*; exits when run as a command, returns when sourced. | |
# --------------------------------------------------------------------------- | |
set -euo pipefail | |
# --------------------------------------------------------------------------- | |
# Detect if nvx is being *sourced* (so we use `return` instead of `exit`) | |
# --------------------------------------------------------------------------- | |
_nvxsourced=0 | |
if [[ "${BASH_SOURCE[0]:-}" != "" && "${BASH_SOURCE[0]}" != "$0" ]]; then | |
_nvxsourced=1 | |
fi | |
nvx_done() { | |
local code="${1:-0}" | |
if [[ $_nvxsourced -eq 1 ]]; then | |
return "$code" | |
else | |
exit "$code" | |
fi | |
} | |
# --------------------------------------------------------------------------- | |
# Ensure $HOME (some sudo/CI contexts lack it) | |
# --------------------------------------------------------------------------- | |
if [[ -z "${HOME:-}" ]]; then | |
export HOME="$(getent passwd "$(id -u)" | cut -d: -f6 || echo /usr/local/lib)" | |
fi | |
# ---- configuration --------------------------------------------------------- | |
NVM_REPO="https://github.com/nvm-sh/nvm.git" | |
MIN_VERSION="${MIN_VERSION:-v0.40.3}" | |
# Prefer user‑specified $NVM_DIR → $HOME/.nvm → /usr/local/.nvm | |
NVM_DIR="${NVM_DIR:-${HOME:+$HOME/.nvm}}"; : "${NVM_DIR:=/usr/local/.nvm}" | |
# --------------------------------------------------------------------------- | |
# --------------------------------------------------------------------------- | |
# Helper: add nvx to the user’s shell startup file once --------------------- | |
# --------------------------------------------------------------------------- | |
auto_init_rc() { | |
local script_path="$(command -v nvx 2>/dev/null || printf '%s' "$0")" | |
local rc | |
case "${SHELL##*/}" in | |
bash) rc="$HOME/.bashrc" ;; | |
zsh) rc="$HOME/.zshrc" ;; | |
fish) rc="$HOME/.config/fish/config.fish" ;; | |
*) rc="$HOME/.profile" ;; | |
esac | |
# Append only if we haven’t already added it | |
if ! grep -qs "source .*nvx" "$rc" 2>/dev/null; then | |
printf '\n# Load nvx (nvm wrapper)\nsource %s\n' "$script_path" >> "$rc" | |
printf '☑️ nvx initialised in %s\n' "$rc" >&2 | |
fi | |
} | |
auto_init_rc # harmless if already present | |
# --------------------------------------------------------------------------- | |
# Install nvm if missing ----------------------------------------------------- | |
# --------------------------------------------------------------------------- | |
install_nvm() { | |
echo "🔧 Installing nvm into $NVM_DIR ..." >&2 | |
git clone --depth 1 "$NVM_REPO" "$NVM_DIR" | |
( | |
cd "$NVM_DIR" | |
git fetch --tags --quiet | |
git -c advice.detachedHead=false checkout "$MIN_VERSION" | |
) | |
} | |
[[ -s "$NVM_DIR/nvm.sh" ]] || install_nvm | |
# --------------------------------------------------------------------------- | |
# Load nvm with auto‑install mode ------------------------------------------- | |
# --------------------------------------------------------------------------- | |
export NVM_AUTO_MODE="install" | |
set +e # tolerate initial nvm_auto failures while sourcing | |
# shellcheck source=/dev/null | |
. "$NVM_DIR/nvm.sh" | |
set -e | |
# --------------------------------------------------------------------------- | |
# Auto .nvmrc hook (always active) ------------------------------------------ | |
# --------------------------------------------------------------------------- | |
if [[ -z ${__NVX_HOOK_LOADED:-} ]]; then | |
__NVX_HOOK_LOADED=1 | |
__nvx_load_nvmrc() { | |
local nvmrc_path="$(nvm_find_nvmrc)" | |
if [[ -n $nvmrc_path ]]; then | |
nvm use --silent --install "$(<"$nvmrc_path")" | |
else | |
[[ "$(nvm current)" == "$(nvm version default)" ]] || nvm use --silent default | |
fi | |
} | |
case "${SHELL##*/}" in | |
zsh) | |
autoload -U add-zsh-hook && add-zsh-hook chpwd __nvx_load_nvmrc ;; | |
fish) | |
cat <<'FISH' | fish -q | |
function __nvx_load_nvmrc --on-variable PWD | |
set nvmrc_path (nvm_find_nvmrc) | |
if test -n "$nvmrc_path" | |
nvm use --silent --install (cat "$nvmrc_path") | |
else if test (nvm current) != (nvm version default) | |
nvm use --silent default | |
end | |
end | |
__nvx_load_nvmrc | |
FISH | |
;; | |
*) PROMPT_COMMAND="__nvx_load_nvmrc${PROMPT_COMMAND:+ ; $PROMPT_COMMAND}" ;; | |
esac | |
fi | |
# Ensure it runs at least once for the starting directory | |
__nvx_load_nvmrc 2>/dev/null || true | |
# --------------------------------------------------------------------------- | |
# Sub‑commands -------------------------------------------------------------- | |
# --------------------------------------------------------------------------- | |
if [[ $# -eq 0 ]]; then | |
nvm --help | |
nvx_done 0 | |
fi | |
if [[ $1 == print-env ]]; then | |
shift | |
nvm use --silent --install "$@" >/dev/null | |
nvm_print_npm_config | |
nvx_done 0 | |
fi | |
if [[ $1 == exec ]]; then | |
shift | |
nvm exec "$@" | |
nvx_done "$?" | |
fi | |
# --------------------------------------------------------------------------- | |
# Forward everything else straight to nvm ------------------------------------ | |
# --------------------------------------------------------------------------- | |
nvm "$@" | |
nvx_done "$?" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The comand below is a drop-in replacement to put this code in
/bin/nvx
. You can make this/bin/nvm
or just stick with switching younvm
commands to the wrappernvx
. I recommend the latter. Using commands likenvm use
then becomesnvx use
.If you have permission issues you might try running the following
export NVM_DIR = $HOME
then re-runnvx
.