Skip to content

Instantly share code, notes, and snippets.

@eoikonomou
Last active March 8, 2024 09:17
Show Gist options
  • Save eoikonomou/74e2b950199cdd21be6697e0aa9cf9af to your computer and use it in GitHub Desktop.
Save eoikonomou/74e2b950199cdd21be6697e0aa9cf9af to your computer and use it in GitHub Desktop.
NVM auto use instructions

NVM automatic version change

Linux Users

Make sure that the correct curl is used in your machine.

  1. Uninstall curl if it is installed using snap by running sudo snap remove curl.
  2. Install curl using apt-get by running sudo apt-get install curl. This is done due to permissions issues with snap curl.

Install nvm if you haven't done so already by running curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash.

Bash users

Add the following script in the end of you $HOME/.bashrc file.

cdnvm() {
    command cd "$@" || return $?
    nvm_path=$(nvm_find_up .nvmrc | tr -d '\n')

    # If there are no .nvmrc file, use the default nvm version
    if [[ ! $nvm_path = *[^[:space:]]* ]]; then

        declare default_version;
        default_version=$(nvm version default);

        # If there is no default version, set it to `node`
        # This will use the latest version on your machine
        if [[ $default_version == "N/A" ]]; then
            nvm alias default node;
            default_version=$(nvm version default);
        fi

        # If the current version is not the default version, set it to use the default version
        if [[ $(nvm current) != "$default_version" ]]; then
            nvm use default;
        fi

    elif [[ -s $nvm_path/.nvmrc && -r $nvm_path/.nvmrc ]]; then
        declare nvm_version
        nvm_version=$(<"$nvm_path"/.nvmrc)

        declare locally_resolved_nvm_version
        # `nvm ls` will check all locally-available versions
        # If there are multiple matching versions, take the latest one
        # Remove the `->` and `*` characters and spaces
        # `locally_resolved_nvm_version` will be `N/A` if no local versions are found
        locally_resolved_nvm_version=$(nvm ls --no-colors "$nvm_version" | tail -1 | tr -d '\->*' | tr -d '[:space:]')

        # If it is not already installed, install it
        # `nvm install` will implicitly use the newly-installed version
        if [[ "$locally_resolved_nvm_version" == "N/A" ]]; then
            nvm install "$nvm_version";
        elif [[ $(nvm current) != "$locally_resolved_nvm_version" ]]; then
            nvm use "$nvm_version";
        fi
    fi
}

alias cd='cdnvm'
cdnvm "$PWD" || exit

Zsh users

Add the following script to your $HOME/.zshrc file.

autoload -U add-zsh-hook

load-nvmrc() {
  local nvmrc_path
  nvmrc_path="$(nvm_find_nvmrc)"

  if [ -n "$nvmrc_path" ]; then
    local nvmrc_node_version
    nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")

    if [ "$nvmrc_node_version" = "N/A" ]; then
      nvm install
    elif [ "$nvmrc_node_version" != "$(nvm version)" ]; then
      nvm use
    fi
  elif [ -n "$(PWD=$OLDPWD nvm_find_nvmrc)" ] && [ "$(nvm version)" != "$(nvm version default)" ]; then
    echo "Reverting to nvm default version"
    nvm use default
  fi
}

add-zsh-hook chpwd load-nvmrc
load-nvmrc

Now every time you get to a folder that contains a .nvmrc file it will automatically detect and use the version stored in there. If you don't have the version already installed it will automatically install it for you and then use it.

Windows Users

CMD Users

Install nvm-windows using the installer that can be found at https://github.com/coreybutler/nvm-windows.

Add the following in a file called cdn.cmd in System32 or any other folder that is included in the path.

@echo off
setlocal EnableDelayedExpansion

if exist %1\.nvmrc ( 
set /p nvm_version=<%1\.nvmrc
nvm install !nvm_version!
nvm use !nvm_version!
) else (
nvm use newest
)
endlocal
cd /d %1

Now you can use the command cdn path\to\destination to move to that folder and if there is any .nvmrc file in the destination folder, the node version will change to whatever that file mentions.

PowerShell Users

Execute the command below in PowerShell to enable running scripts on the system: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force

Add the following file in the Profile Path %UserProfile%/Documents/WindowsPowerShell/Microsoft.PowerShell_profile.ps1:

Function My-Cd {
    param (
        $path
    )
    
    # Run default "cd" command
    Set-Location -Path $path
    if (-not $?) { return }
    
    $nvm = @{
        folder      = "$env:AppData/nvm/"
        isInstalled = $null
        url         = 'https://github.com/coreybutler/nvm-windows/releases/latest'
        webdata     = $null
        download    = $null
        tmp         = "$env:TMP/nvm-setup.exe"
    }

    $node = @{
        folder      = "$env:ProgramFiles\nodejs"
        isPresent   = $null
        newest      = $null
        current     = $null
        isCurrent   = $null
    }
    
    $nvmrc = @{
        path        = '.nvmrc'
        isFound     = $null
        version     = $null
        isInstalled = $null
        isCurrent   = $null
    }
    
    # Check for NVM Installation
    $nvm.isInstalled    = Test-Path $nvm.folder -PathType Container
    $node.isPresent     = Test-Path $node.folder -PathType Container
    if (-not $nvm.isInstalled) {
        # Check for Node.js Installation & display error
        if ($node.isPresent) {
            Add-Type -AssemblyName PresentationCore,PresentationFramework
            [System.Windows.MessageBox]::Show(
                "Uninstall ""Node.js"" and delete ""$($node.folder)""",
                'Node.js installation found!',
                'Ok',
                'Warning'
            )
            return
        }
        
        # Download & Install NVM for Windows
        $nvm.webdata    = Invoke-RestMethod $nvm.url
        $nvm.download   = (($nvm.webdata | Select-String 'app-argument=(.*?)"').Matches.Groups[1].Value).Replace('tag', 'download') + '/nvm-setup.exe'
        #$ProgressPreference = "SilentlyContinue"   # Hide download progress
        'Downloading latest NVM for Windows...'
        Start-BitsTransfer -Source $nvm.download -Destination $nvm.tmp -DisplayName 'Downloading latest NVM for Windows...'
        'Installing latest NVM for Windows...'
        Start-Process $nvm.tmp '/SP- /VERYSILENT /SUPPERMSGSBOXES /NORESTART' -Wait
        Remove-Item $nvm.tmp
        
        # Update Environment Variables
        $env:NVM_HOME = [System.Environment]::GetEnvironmentVariable("NVM_HOME","Machine")
        $env:NVM_SYMLINK = [System.Environment]::GetEnvironmentVariable("NVM_SYMLINK","Machine")
        $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine")
    }
    else {
        # Get current NVM Version
        if ($node.isPresent) {
            $node.current = (Get-Item $node.folder).target[0]
        }
    }
    
    $nvmrc.isFound = Test-Path $nvmrc.path -PathType Leaf
    if ($nvmrc.isFound) {
        # If .nvmrc exists: Install/Use .nvmrc's Node.js version
        $nvmrc.version      = Get-Content $nvmrc.path -First 1
        $nvmrc.isInstalled  = ([array](Get-ChildItem $nvm.folder -Directory).Name -Match "^$($nvmrc.version)")[0]
        if (-not $nvmrc.isInstalled) {
            "Installing Node.js $($nvmrc.version)..."
            Start-Process nvm "install $($nvmrc.version)" -WindowStyle Hidden -Wait
        }
        $nvmrc.isCurrent = $(if ($node.isPresent) { $node.current.Contains($nvmrc.version) })
        if (-not $nvmrc.isCurrent) {
            "Using Node.js $($nvmrc.version)..."
            Start-Process nvm "use $($nvmrc.version)" -Verb RunAs -WindowStyle Hidden -Wait
        }
     }
     else {
        # If .nvmrc doesn't exist: Install/Use Latest/Newest Node.js
        $node.newest = ([array](Get-ChildItem $nvm.folder -Directory).Name -Match '^v\d+')[-1]
        if (-not $node.newest) {
            'Downloading latest Node.js version...'
            Start-Process nvm "install latest" -WindowStyle Hidden -Wait
            $node.newest = ([array](Get-ChildItem $nvm.folder -Directory).Name -Match '^v\d+')[-1]
        }
        $node.isCurrent = $(if ($node.isPresent) { $node.current.Contains($node.newest) })
        if (-not $node.isCurrent) {
            "Using Node.js $($node.newest)..."
            Start-Process nvm 'use newest' -Verb RunAs -WindowStyle Hidden -Wait
        }
     }
}

# Override "cd" alias
Set-Alias -Name 'cd' -Value 'My-Cd' -Option AllScope
cd .

With this setup every time the PowerShell opens or you cd in a folder with an .nvmrc file present, it will automatically isntall and use it. If no .nvmrc is present it will switch to the default node version.

Mac Users

Install nvm if you haven't done so already by running curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash.

Bash users

Add the following script in the end of you $HOME/.bashrc file.

cdnvm() {
    command cd "$@" || return $?
    nvm_path=$(nvm_find_up .nvmrc | tr -d '\n')

    # If there are no .nvmrc file, use the default nvm version
    if [[ ! $nvm_path = *[^[:space:]]* ]]; then

        declare default_version;
        default_version=$(nvm version default);

        # If there is no default version, set it to `node`
        # This will use the latest version on your machine
        if [[ $default_version == "N/A" ]]; then
            nvm alias default node;
            default_version=$(nvm version default);
        fi

        # If the current version is not the default version, set it to use the default version
        if [[ $(nvm current) != "$default_version" ]]; then
            nvm use default;
        fi

    elif [[ -s $nvm_path/.nvmrc && -r $nvm_path/.nvmrc ]]; then
        declare nvm_version
        nvm_version=$(<"$nvm_path"/.nvmrc)

        declare locally_resolved_nvm_version
        # `nvm ls` will check all locally-available versions
        # If there are multiple matching versions, take the latest one
        # Remove the `->` and `*` characters and spaces
        # `locally_resolved_nvm_version` will be `N/A` if no local versions are found
        locally_resolved_nvm_version=$(nvm ls --no-colors "$nvm_version" | tail -1 | tr -d '\->*' | tr -d '[:space:]')

        # If it is not already installed, install it
        # `nvm install` will implicitly use the newly-installed version
        if [[ "$locally_resolved_nvm_version" == "N/A" ]]; then
            nvm install "$nvm_version";
        elif [[ $(nvm current) != "$locally_resolved_nvm_version" ]]; then
            nvm use "$nvm_version";
        fi
    fi
}

alias cd='cdnvm'
cdnvm "$PWD" || exit

Zsh users

Add the following script to your $HOME/.zshrc file.

autoload -U add-zsh-hook

load-nvmrc() {
  local nvmrc_path
  nvmrc_path="$(nvm_find_nvmrc)"

  if [ -n "$nvmrc_path" ]; then
    local nvmrc_node_version
    nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")

    if [ "$nvmrc_node_version" = "N/A" ]; then
      nvm install
    elif [ "$nvmrc_node_version" != "$(nvm version)" ]; then
      nvm use
    fi
  elif [ -n "$(PWD=$OLDPWD nvm_find_nvmrc)" ] && [ "$(nvm version)" != "$(nvm version default)" ]; then
    echo "Reverting to nvm default version"
    nvm use default
  fi
}

add-zsh-hook chpwd load-nvmrc
load-nvmrc

Now every time you get to a folder that contains a .nvmrc file it will automatically detect and use the version stored in there. If you don't have the version already installed it will automatically install it for you and then use it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment