Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Please consider decoupling nvm implementation to allow use with other node managers #5505

Open
f1yn opened this issue Dec 17, 2022 · 0 comments

Comments

@f1yn
Copy link

f1yn commented Dec 17, 2022

What's going wrong?

I don't like nvm. It's coarse, and rough, and irritating, and it gets everywhere. Not like fnm. fnm (everything) is soft, and smooth.

For every other project I use, I opt to use fnm as it's faster, works more consistently, and does less whacky crap to the environment (it's also only possible to install a single way). Unfortunately, it only offers compatibility at the cli level, and does not use the same weird bash structure that nvm uses.

pm2 directly attempts to call nvm.sh and will access the node versions directly, relative to the installation. To provide compatibility with more node management systems, it might be easier just to provide the ability to leverage the existing commands that nvm, like nvm exec that are also replicated by other node version managers. Most commands are replicated 1:1, all of the ones needed for pm2 to do what it needs to do anyways.

How could we reproduce this issue?

Look at the code here:

pm2/lib/Common.js

Lines 376 to 415 in da59cb6

var nvm_path = cst.IS_WINDOWS ? process.env.NVM_HOME : process.env.NVM_DIR;
if (!nvm_path) {
Common.printError(cst.PREFIX_MSG_ERR + chalk.red('NVM is not available in PATH'));
Common.printError(cst.PREFIX_MSG_ERR + chalk.red('Fallback to node in PATH'));
var msg = cst.IS_WINDOWS
? 'https://github.com/coreybutler/nvm-windows/releases/'
: '$ curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash';
Common.printOut(cst.PREFIX_MSG_ERR + chalk.bold('Install NVM:\n' + msg));
}
else {
var node_version = app.exec_interpreter.split('@')[1];
var path_to_node = cst.IS_WINDOWS
? '/v' + node_version + '/node.exe'
: semver.satisfies(node_version, '>= 0.12.0')
? '/versions/node/v' + node_version + '/bin/node'
: '/v' + node_version + '/bin/node';
var nvm_node_path = path.join(nvm_path, path_to_node);
try {
fs.accessSync(nvm_node_path);
} catch(e) {
Common.printOut(cst.PREFIX_MSG + 'Installing Node v%s', node_version);
var nvm_bin = path.join(nvm_path, 'nvm.' + (cst.IS_WINDOWS ? 'exe' : 'sh'));
var nvm_cmd = cst.IS_WINDOWS
? nvm_bin + ' install ' + node_version
: '. ' + nvm_bin + ' ; nvm install ' + node_version;
Common.printOut(cst.PREFIX_MSG + 'Executing: %s', nvm_cmd);
execSync(nvm_cmd, {
cwd: path.resolve(process.cwd()),
env: process.env,
maxBuffer: 20 * 1024 * 1024
});
// in order to support both arch, nvm for Windows renames 'node.exe' to:
// 'node32.exe' for x32 arch
// 'node64.exe' for x64 arch
if (cst.IS_WINDOWS)
nvm_node_path = nvm_node_path.replace(/node/, 'node' + process.arch.slice(1))
}

In the end, it's still executing synchronous commands to trigger nvm actions. However, it's relying on fixed file structures - which makes it difficult to integrate fnm as it's expecting these to always exist of relying on known command line compatibility between managers.

For context, we use pm2 as a development tool as it has great monitoring and management features built in. This means we aren't always fixated on making sure everyone is spawning and running things the exact same way - that's what our continuous delivery pipeline is for. I'd rather not haphazardly bork the ecosystem file, or ask my coworkers to install my favourite tool or their dev systems wont work anymore.

The other option is to dynamically convert the export in the ecosystem file to directly use fnm, but that's even more annoying and confusing.

I can make these changes and submit a PR, but I wanted to understand the decision behind keeping so close to nvm. I don't want to make a PR if it wont be merged for reasons I don't know yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant