#!/bin/sh usage() { cat << EOF usage: $0 [-d] [-v] This script is intended to fix the common problem where npm users are required to use sudo to install global packages. It will backup a list of your installed packages remove all but npm, then create a local directory, configure node to use this for global installs whilst also fixing permissions on the .npm dir before, reinstalling the old packages. OPTIONS: -h Show this message -d debug -v Verbose EOF } DEBUG=0 VERBOSE=0 while getopts "dv" OPTION do case $OPTION in d) DEBUG=1 ;; v) VERBOSE=1 ;; ?) usage exit ;; esac done to_reinstall='/tmp/npm-reinstall.txt' if [ 1 = ${VERBOSE} ]; then printf "\nSaving list of existing global npm packages\n" fi #Get a list of global packages (not deps) #except for the npm package #save in a temporary file. npm -g list --depth=0 --parseable --long | cut -d: -f2 | grep -v '^npm@\|^$' >$to_reinstall if [ -f $NVM_DIR/nvm.sh ]; then printf "Found a possible nvm install - this script may cause issues, so will exit\n" printf "a list of your current node's npm packages is in $to_reinstall\n\n" printf "If you save this file somewhere else, e.g. ~/npm-reinstall.txt, you can run\n\n" printf "cat ~/npm-reinstall.txt | xargs npm -f install\n\n" printf "when you add new node versions with nvm\n" exit fi if [ 1 = ${VERBOSE} ]; then printf "\nRemoving existing packages temporarily - you might need your sudo password\n\n" fi #List the file #replace the version numbers #remove the newlines #and pass to npm uninstall uninstall='sudo npm -g uninstall' if [ 1 = ${DEBUG} ]; then printf "Won't uninstall\n\n" uninstall='echo' fi if [ -s $to_reinstall ]; then cat $to_reinstall | sed -e 's/@.*//' | xargs $uninstall fi defaultnpmdir="${HOME}/.npm-packages" npmdir='' read -p "Choose your install directory. Default (${defaultnpmdir}) : " npmdir if [ -z ${npmdir} ]; then npmdir=${defaultnpmdir} else if [ ! -d ${npmdir} ]; then echo "${npmdir} is not a directory." exit fi npmdir="${npmdir}/.npm-packages" fi if [ 1 = ${VERBOSE} ]; then printf "\nMake a new directory ${npmdir} for our "-g" packages\n" fi if [ 0 = ${DEBUG} ]; then mkdir -p ${npmdir} npm config set prefix $npmdir fi if [ 1 = ${VERBOSE} ]; then printf "\nFix permissions on the .npm directories\n" fi me=`whoami` sudo chown -R $me $npmdir if [ 1 = ${VERBOSE} ]; then printf "\nReinstall packages\n\n" fi #list the packages to install #and pass to npm install='npm -g install' if [ 1 = ${DEBUG} ]; then install='echo' fi if [ -s $to_reinstall ]; then cat $to_reinstall | xargs $install fi envfix=' export NPM_PACKAGES="%s" export NODE_PATH="$NPM_PACKAGES/lib/node_modules${NODE_PATH:+:$NODE_PATH}" export PATH="$NPM_PACKAGES/bin:$PATH" # Unset manpath so we can inherit from /etc/manpath via the `manpath` # command unset MANPATH # delete if you already modified MANPATH elsewhere in your config export MANPATH="$NPM_PACKAGES/share/man:$(manpath)" ' fix_env() { if [ -f "${HOME}/.bashrc" ]; then printf "${envfix}" ${npmdir} >> ~/.bashrc printf "\nDon't forget to run 'source ~/.bashrc'\n" fi if [ -f "${HOME}/.zshrc" ]; then printf "${envfix}" ${npmdir} >> ~/.zshrc printf "\nDon't forget to run 'source ~/.zshrc'\n" fi } echo_env() { printf "\nYou may need to add the following to your ~/.bashrc / .zshrc file(s)\n\n" printf "${envfix}\n\n" ${npmdir} } printf "\n\n" read -p "Do you wish to update your .bashrc/.zshrc file(s) with the paths and manpaths? [yn] " yn case $yn in [Yy]* ) fix_env;; [Nn]* ) echo_env;; * ) printf "\nInvalid choice\n"; echo_env;; esac rm $to_reinstall printf "\nDone - current package list:\n\n" npm -g list -depth=0