nvm icon indicating copy to clipboard operation
nvm copied to clipboard

Semver range support

Open alexkrolick opened this issue 4 years ago • 15 comments

I know the preferred way to reference ranges in nvm is with lts/name, but we've run into an issue when pkg.engines has to specify a minimum value for the minor version, ie >= 10.13.1. Without switching to an exact version, users who don't habitually update their nvm references will not get the memo to update to the minimum.

Allowing ^10.13.1 or something like that would allow a minimum version without capping the maximum version, which is desirable.

alexkrolick avatar Aug 20 '21 00:08 alexkrolick

pkg.engines is a range, altho it's often used in apps to target a single version.

nvm does not in fact support ranges - lts/ aliases target a single version out of a subset. lts/argon, for example, means v4.9.1, and only that version, full stop.

Is your use case for an app, or a package?

ljharb avatar Aug 20 '21 02:08 ljharb

The use case is for an app.

lts/argon, for example, means v4.9.1, and only that version, full stop.

Right, the problem is since it's a rolling pointer, if a dev doesn't update the reference using nvm install periodically, they can fall behind without knowing it. So if you rely on behavior from a minimal version in a release series specified in pkg.engines, and assume that lts/whatever will be the maximum of that release series, you can run into an issue when a local pointer is lagging. Hence the desire to increase specificity of the minimum version while still allowing a higher maximum version.

alexkrolick avatar Aug 20 '21 18:08 alexkrolick

I see - so if I understand correctly, you want a way in .nvmrc to say lts/argon but ALSO to say 4.9.1, so that if someone has a local lts/argon that's behind, they'll get a warning?

Note that any remote connection will update the local user - you could, for example, add to your app's preinstall script something like nvm version-remote node >/dev/null and it will silently update their local aliases, so that nvm use will report that the right node is not installed. Would that suffice?

ljharb avatar Aug 20 '21 18:08 ljharb

I see - so if I understand correctly, you want a way in .nvmrc to say lts/argon but ALSO to say 4.9.1, so that if someone has a local lts/argon that's behind, they'll get a warning?

Yes, but it seems fairly hard to express that with release codenames, so semver notation like ^4.9.1 or the equivalent >=4.9.1 < 5 would also work.

Note that any remote connection will update the local user

I suppose this works. It's not precise but I guess in combination with the engines field, the end result will be that devs roll forward whenever possible and can't install on less than the minimum version.

alexkrolick avatar Aug 20 '21 22:08 alexkrolick

Unfortunately to parse semver notation would require a very large and complex chunk of code in shell scripting, so that's not really feasible.

ljharb avatar Aug 20 '21 22:08 ljharb

I'll settle for documenting the workflow above, but I'll also propose this if it seems valuable to automate:

4.9.1 # installs just this
lts/argon # installs local pointer
min: 4.9.1 # same as just 4.9.1
max: 4.9.1 # same as just 4.9.1
max: lts/argon # same as lts/argon
min: 4.9.1
max: lts/argon # installs lts/argon unless it is behind min
min: 5
max: 4 # error

(I think the formal way is also better than automating the fetch using package scripts because some people may need to use the --reinstall-packages-from flag to properly update)

alexkrolick avatar Aug 20 '21 22:08 alexkrolick

We'd need to define semantics for min: 4.9, max: 4.9, etc; also, nvm doesn't track which versions used to be LTS - not sure if that'd be required.

ljharb avatar Aug 20 '21 22:08 ljharb

nvm doesn't track which versions used to be LTS - not sure if that'd be required.

I don't think it would be, you'd just turn the local lts pointer into a fully qualified version and see if it matches the constraint

alexkrolick avatar Aug 20 '21 22:08 alexkrolick

What if the .nvmrc file specified a list of supported versions, and it used the first version to match locally installed versions:

14.12.*
14.19.*
16.*.*
12.17.*

If this is breaking change, then perhaps a .node-versions (plural) file would be appropriate?

justsml avatar Feb 16 '22 20:02 justsml

@justsml nvm doesn't understand stars like that, but 14.12, 14.19, etc would work. However, it would definitely be a breaking change.

Something with a non-nvm-specific name wouldn't be able to support nvm-specific ranges, like aliases, or 14.12 - it'd have to take full versions only.

ljharb avatar Feb 16 '22 23:02 ljharb

Using the following in .nvmrc works for us, but...

node-version = >=14.19.1||<15.0.0
engine-strict = true

We get a semver warning npm WARN invalid config node-version=">=14.19.1||<15.0.0". Any way to turn that off?

FranCarstens avatar Aug 09 '22 14:08 FranCarstens

@FranCarstens that's npmrc, not nvmrc, and that definitely will not work for nvm.

ljharb avatar Aug 09 '22 18:08 ljharb

(re engines.node, linking to #651)

ljharb avatar Oct 24 '22 04:10 ljharb

Just to mention that we encountered same problem in our app.

Some of our app's dependency packages require Node >= 16.14, and we are strugging how to set a corrresponding version in app's .nvmrc.

Option 1: v16 in .nvmrc If 16.12 is the shell's original nvm default, it won't be aware that it should install and switch to 16.14 even with integration, because 16.12 is satisfying v16 in .nvmrc.

Option 2: v16.14 in .nvmrc It comes up with two problems. First, if someone has 16.18 as default on her local machine, she has no choice but to install 16.14 -- even 16.18 has satisfied the >= 16.14 requirement in package.json. The second is that both package.json engines.node field and .nvmrc are specifying Node version

leannechen avatar Dec 19 '23 09:12 leannechen

@leannechen add a CI check that both are in sync, and you shouldn’t want some devs on 16.18 if your app is tested and deployed on 16.14 - iow, for an app, you should use a full 1.2.3 version.

ljharb avatar Dec 19 '23 15:12 ljharb