nvm-sh / nvm

Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions
MIT License
80.7k stars 8.05k forks source link

.nvmrc for projects #110

Closed westoque closed 11 years ago

westoque commented 12 years ago

It would be nice if we had a ".nvmrc" file for a project, kind of like ".rvmrc" for ruby. I'll start prototyping this later. What do you guys think?

creationix commented 12 years ago

I'm not sure what it would do. NVM doesn't wrap the node executable, it just helps you manage multiple $PATH values.

booo commented 12 years ago

Switch to the node version specified in .nvmrc? Why not use the package.json file?

creationix commented 12 years ago

But what will do the switching? Are you going to run nvm readconfig or something every time you enter a new folder?

booo commented 12 years ago

As far as I know the rvm checks on every cd if the new folder contains a rvmrc and loads the appropriate config/ruby version. Maybe a ruby expert should say something about this :)

http://beginrescueend.com/workflow/rvmrc/

westoque commented 12 years ago

I just looked at how rvm implemented this. I am going to do the same approach.

slaskis commented 12 years ago

I like this idea too, except that using the package.json instead of a separate .npmrc makes a a lot of sense to me as @booo says

chakrit commented 12 years ago

There is already an engine version specified in the package.json file. There is zero need to add yet another dotfile to do this.

I'd love for nvm to do this automatically as well. But definitely not by adding yet another .whateverc.

abe33 commented 12 years ago

Hi guys,

For those interested, I spent some time this week end to write a proof of concept around the idea of parsing the package.json on a cd. Actually I use a ruby script to parse the json file and define what to do, since my bash-jutsu is quite limited. I didn't work much on the version operators either, so there's only a limited support (>=, <= and = are supported actually).

The fork can be found here: https://github.com/abe33/nvm/tree/feature_automatic_use_on_cd_with_package

chakrit commented 12 years ago

Idea: regarding "auto-switching", would it be better if we just add an nvm command to pick the best version that's suited to the current folder's package.json?

something like

nvm select # auto-select a local version that best matches what's specified in package.json

I have used rvm before and honestly didn't like the cd-stealing approach. I already have a few commands that try to steal my cd (autojump and rvm for example) and does some extra processings that I'm not aware of. IMO, running anything automatically on a cd is a bad approach.

abe33 commented 12 years ago

@chakrit : The last version includes the nvm select command as you requested and dissociate the change directory hook in a separate file. I also added the support for all the version range expressions (as documented here: https://npmjs.org/doc/json.html#dependencies, minus the git and http ones). I guess there's some edge cases I didn't tested yet, I'll update it as soon as I'll find them.

chakrit commented 12 years ago

@abe33 nice! :) using your fork right now.

EDIT: ruby? ಠ__ಠ

abe33 commented 12 years ago

@chakrit : Yes, as I said in my first comment, my skills with shell script aren't that good, and I had hard times to find out how to parse a json file with pure shell - re-writing a json parser wasn't really part of the plan ^^ - and writing the version matching algorithm was beyond my knowledge by far. If people have advice to how implement this in shell, I'll gladly try to port the ruby code :).

tiye commented 11 years ago

Related feature requst: http://cnodejs.org/topic/516a1f0e6d382773062dfd8a I think use packge.json for auto-switching is a nice solution.

ghost commented 11 years ago

I also think it would be nice to add an nvm command that can try to figure out the engine to use by parsing the package.json. I have a lot of projects with different node versions, so it’d be a time saver if I don’t have to go look into package.json myself to figure out which version I want to tell nvm to use.

ghost commented 11 years ago

But yeah, I’m not sure how easy it is to parse package.json in pure Bash.

creationix commented 11 years ago

@hydrozen sounds like you need a new tool. Let's not bloat nvm with complex features like this. Searching recursively through package.json files is non-trivial for a bash function. (parsing a single json file in bash is hard enough) Write a new tool that works in any version of node that outputs a string for the ideal node version to run, and then pass that string to nvm.

creationix commented 11 years ago

I'm going to close this issue. After thinking about this for a while, it's outside the scope of nvm. Nvm is used to install and switch between versions of node manually. There is an automatic default version, but I really want to keep the tool simple.

I do think it would be a great project for someone to create a new tool written in node.js that looks at the package.json files in the current working tree and outputs the ideal node version to run. This tool will need to be installed somewhere outside nvm's tree and in your $PATH so that it will stay in scope as you switch between node versions. It can use #!/bin/env node in it's shebang. JSON parsing and file reading API's haven't changed in node in a long time, so it should run in nearly any version you want to use.

abe33 commented 11 years ago

@creationix No pb for me, the ruby code can easily be ported to js so I'll give it a try when I can find some spare time.

ziyan-junaideen commented 11 years ago

It will be a cool thing to have!

potomak commented 11 years ago

I would pay 2$ if somebody implements this feature.

creationix commented 11 years ago

@potomak you'll pay someone to write a patch I've said I won't accept, or pay someone to write a separate utility as I suggested? (If it's the first, you'll just have to maintain a fork to keep the patch. there won't be hurt feelings)

potomak commented 11 years ago

@creationix the best would be to get this patch merged inside your repo (note I'd give part of that bounty to you as the maintainer of the project) but I could pay also for the second solution.

chakrit commented 11 years ago

@creationix plugin nag : )

koenpunt commented 11 years ago

The .nvmrc is already read when calling nvm use, so what is the point of this issue? Or is it me being ignorant right now?

creationix commented 11 years ago

@koenpunt right, I was talking about parsing package.json in nvm. That's outside the scope of the project.

ghost commented 11 years ago

I didn’t even know about the .nvmrc file. That’s good enough for me.

cdnbacon commented 11 years ago

@creationix Have you considered something like this?

nvm use $(node -e 'console.log(require("./package.json").engines.node)')
koenpunt commented 11 years ago

That doesn't work if the engine is defined as >=0.4.0..

cdnbacon commented 11 years ago

@koenpunt , depending on the semantics you desire, you can use something like this if you want to use the least-recent supported version in package.json

nvm use $(node -e 'console.log(require("./package.json").engines.node.replace(/[^\d\.]+/g, ""))')
potomak commented 11 years ago

That's not the only exception, see https://npmjs.org/doc/json.html and https://github.com/isaacs/node-semver

Version range descriptors may be any of the following styles, where "version" is a semver compatible version identifier.

  • version Must match version exactly
  • =version Same as just version
  • >version Must be greater than version
  • >=version etc
  • <version
  • <=version
  • ~version See 'Tilde Version Ranges' below
  • 1.2.x See 'X Version Ranges' below
  • http://... See 'URLs as Dependencies' below
  • * Matches any version
  • "" (just an empty string) Same as *
  • version1 - version2 Same as >=version1 <=version2.
  • range1 || range2 Passes if either range1 or range2 are satisfied.
  • git... See 'Git URLs as Dependencies' below
j1n6 commented 11 years ago

@koenpunt useful tip. It would be nice if this is automatically called after navigating to the folder that containing .nvmrc

ljharb commented 11 years ago

@activars you'd have to patch "cd" for that, which is far outside of the scope of nvm :-)

ronkorving commented 11 years ago

I've written the following shell script, which depends on the semver module to pick exactly the perfect node version (latest version possible, as allowed by the engines field):

function getFromPackage () {
    $(which node) -e "console.log(require('./package.json').${1})";

    if [ "$?" != "0" ]; then
        echo "Not found in package.json: $1";
        exit 1;
    fi
}

node () {
    nvmPath="/nvm";
    semverPath="$nvmPath/v0.8.25/bin/semver";

    range=getFromPackage('engines.node');

    nodeVersions=$(find "$nvmPath" -maxdepth 1 -type d -name 'v*' -printf '%f\n');
    if [ "${nodeVersions}" = "" ]; then
        echo "No installed Node.js versions could be found in $nvmPath";
        return 1;
    fi;

    nodeVer=$($semverPath --range "$range" $nodeVersions | tail -1);
    if [ "${nodeVer}" = "" ]; then
        echo "No installed Node.js versions match range '${range}'";
        return 1;
    fi;

    (nvm use $nodeVer > /dev/null 2>&1 && $(which node) $*);

    ret=$?;

    tset;
    return $ret;
}

I'm sure it's not perfect, but could be the basis for something better? Feedback encouraged :)

denysonique commented 11 years ago

This is very important. As let say I only want to run with versoin 0.11.2 not higher. E.g if I run with a higher version of node my database data could get corrupted. An 'nvmrc' implementation would prevent this.

koenpunt commented 11 years ago

@denysonique If that's the case you should probably do some version checking in your app..?

ljharb commented 11 years ago

@denysonique Odd versions of node are unstable. You shouldn't be using them with production data, ever.

wbyoung commented 10 years ago

For anyone interested in building a robust tool similar to what RVM is doing, most of the code for how RVM handles this seems to be in here and here.

intuivo commented 10 years ago

Quick Fix: IF YOU USE rvm already... or you just just have it installed:

  1. Create an .rvmrc file touch .rvmrc
  2. subl .rvmrc
  3. type nvm use 0.11
  4. save
  5. Go up cd .. and go in the your folder.

RVM will execute it anyways.

dgmike commented 10 years ago

@intuivo in this case, I prefer to use autoenv https://github.com/kennethreitz/autoenv

igorescobar commented 10 years ago

@creationix I think that feature would be very welcome to NVM and I still think that it wouldn't make NVM more complex at all.

j1n6 commented 10 years ago

It's also useful for each CI environment as well. so that each project in the CI are isolated automatically by nvm.

igorescobar commented 10 years ago

@activars #truestory :+1:

koenpunt commented 10 years ago

@activars to quote myself:

The .nvmrc is already read when calling nvm use, so what is the point of this issue? Or is it me being ignorant right now?

So in a CI environment you would only have to run nvm use to have the correct node environment.

igorescobar commented 10 years ago

@activars the point of using the .nvmrc like .rvmrc is that you don't need to run any other command to make it work. When go inside of your project's folder RVM automatically loads the correct ruby version based on the .rvmrc file... no need to run nvm use.

igorescobar commented 10 years ago

nvm use is nice but it could be nicer if it could work like rvm/rbenv/pyenv already does.

koenpunt commented 10 years ago

This is because rvm patches cd, which I don't like. And rbenv creates so called "shims" which load the environment. Which could be an option, create ~/.nvm/bin/node which detects if there is a .nvmrc file in the current directory.

But this would mean these "shims" have to be created for every binary like coffee, grunt, lesscss

j1n6 commented 10 years ago

I quite like the shin approach.

Sent from my iPhone

On 15 Apr 2014, at 18:28, Koen Punt notifications@github.com wrote:

This is because rvm patches cd, which I don't like. And rbenv creates so called "shims" which load the environment. Which could be an option, create ~/.nvm/bin/node which detects if there is a .nvmrc file in the current directory.

But this would mean these "shims" have to be created for every binary.

— Reply to this email directly or view it on GitHub.

ljharb commented 10 years ago

rbenv-style shims and patching cd are far outside the scope of this project, and won't happen.

Let's all please stop providing additional plus ones - If anyone wants to open a PR, or file an issue, for a very tightly focused and small way that nvm can utitilize .nvmrc, I'm happy to consider it - see #318 - but this issue will remain closed.

wbyoung commented 10 years ago

I think what some of the commenters here are missing is that this project team isn't saying the solution shouldn't exist. They're saying that it shouldn't be part of this project.

There's nothing prohibiting someone from creating a tool, auto-nvm-env, that reads .nvmrc (or .node_version to mirror rvm's support for .ruby_version). In fact, it sounds like that's what they'd encourage.

igorescobar commented 10 years ago

@wbyoung I can't see why it shouldn't be part of NVM but ok... you already made a decision 2 years ago ;-)