Skip to content

Commit b6bc159

Browse files
ljharbwesleytodd
authored andcommitted
feat: add engines and cwd options
1 parent 98fb2a9 commit b6bc159

File tree

6 files changed

+246
-1
lines changed

6 files changed

+246
-1
lines changed

README.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,109 @@ console.log(versions.map((v) => v.version))
113113
*/
114114
```
115115

116+
## Command line interface (CLI)
117+
118+
Options:
119+
- `--only-version`: instead of the entire output, only print one version number per line
120+
- `--engines`: only print versions that match the current directory's `engines.node` field
121+
- `--engines=lts`: only print LTS versions that also match the current directory's `engines.node` field
122+
123+
```sh
124+
$ nv ls lts
125+
{
126+
"version": "18.20.4",
127+
"major": 18,
128+
"minor": 20,
129+
"patch": 4,
130+
"tag": "",
131+
"codename": "hydrogen",
132+
"versionName": "v18",
133+
"start": "2022-04-19T00:00:00.000Z",
134+
"lts": "2022-10-25T00:00:00.000Z",
135+
"maintenance": "2023-10-18T00:00:00.000Z",
136+
"end": "2025-04-30T00:00:00.000Z",
137+
"releaseDate": "2024-07-08T00:00:00.000Z",
138+
"isLts": true,
139+
"files": [
140+
"aix-ppc64",
141+
"headers",
142+
"linux-arm64",
143+
"linux-armv7l",
144+
"linux-ppc64le",
145+
"linux-s390x",
146+
"linux-x64",
147+
"osx-arm64-tar",
148+
"osx-x64-pkg",
149+
"osx-x64-tar",
150+
"src",
151+
"win-x64-7z",
152+
"win-x64-exe",
153+
"win-x64-msi",
154+
"win-x64-zip",
155+
"win-x86-7z",
156+
"win-x86-exe",
157+
"win-x86-msi",
158+
"win-x86-zip"
159+
],
160+
"dependencies": {
161+
"npm": "10.7.0",
162+
"v8": "10.2.154.26",
163+
"uv": "1.44.2",
164+
"zlib": "1.3.0.1-motley",
165+
"openssl": "3.0.13+quic"
166+
}
167+
}
168+
{
169+
"version": "20.15.1",
170+
"major": 20,
171+
"minor": 15,
172+
"patch": 1,
173+
"tag": "",
174+
"codename": "iron",
175+
"versionName": "v20",
176+
"start": "2023-04-18T00:00:00.000Z",
177+
"lts": "2023-10-24T00:00:00.000Z",
178+
"maintenance": "2024-10-22T00:00:00.000Z",
179+
"end": "2026-04-30T00:00:00.000Z",
180+
"releaseDate": "2024-07-08T00:00:00.000Z",
181+
"isLts": true,
182+
"files": [
183+
"aix-ppc64",
184+
"headers",
185+
"linux-arm64",
186+
"linux-armv7l",
187+
"linux-ppc64le",
188+
"linux-s390x",
189+
"linux-x64",
190+
"osx-arm64-tar",
191+
"osx-x64-pkg",
192+
"osx-x64-tar",
193+
"src",
194+
"win-arm64-7z",
195+
"win-arm64-zip",
196+
"win-x64-7z",
197+
"win-x64-exe",
198+
"win-x64-msi",
199+
"win-x64-zip",
200+
"win-x86-7z",
201+
"win-x86-exe",
202+
"win-x86-msi",
203+
"win-x86-zip"
204+
],
205+
"dependencies": {
206+
"npm": "10.7.0",
207+
"v8": "11.3.244.8",
208+
"uv": "1.46.0",
209+
"zlib": "1.3.0.1-motley",
210+
"openssl": "3.0.13+quic"
211+
}
212+
}
213+
214+
$ nv ls lts --only-version
215+
18.20.4
216+
20.15.1
217+
```
218+
116219
## Supported Aliases
117220

118221
**Support Aliases**

bin/nv

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,14 @@ require('yargs')
2727
type: 'boolean',
2828
description: 'show version number only'
2929
})
30+
yargs.option('engines', {
31+
type: 'string',
32+
description: 'read the value of `engines.node`. if a value is provided, and it satisfies, the version is shown; if not, the max satisfying version is shown'
33+
})
3034
},
3135
handler: (argv) => {
3236
nv(argv.versions, {
37+
engines: argv.engines,
3338
mirror: argv.mirror,
3439
latestOfMajorOnly: argv.latestOfMajorOnly
3540
})
@@ -47,7 +52,7 @@ require('yargs')
4752
})
4853
}).catch(e => {
4954
console.error(e)
50-
process.exitCode = e.code || 1
55+
process.exitCode ||= e.code || 1
5156
})
5257
}
5358
})

index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
'use strict'
2+
const { readFile } = require('fs/promises')
3+
const { join } = require('path')
4+
25
const got = require('got')
36
const semver = require('semver')
47
const _cache = new Map()
@@ -9,6 +12,8 @@ module.exports = async function (alias = 'lts_active', opts = {}) {
912
const mirror = opts.mirror || 'https://nodejs.org/dist/'
1013
const latestOfMajorOnly = opts.latestOfMajorOnly || false
1114
const ignoreFutureReleases = opts.ignoreFutureReleases || false
15+
const engines = opts.engines
16+
const cwd = opts.cwd || process.cwd()
1217

1318
const a = Array.isArray(alias) ? alias : [alias]
1419
const versions = await getLatestVersionsByCodename({
@@ -31,6 +36,18 @@ module.exports = async function (alias = 'lts_active', opts = {}) {
3136
return m
3237
}, {})
3338

39+
if (typeof engines === 'string' || engines === true) {
40+
const { engines: { node } = { node: '*' } } = JSON.parse(await readFile(join(cwd, 'package.json'), 'utf8'))
41+
42+
m = Object.fromEntries(Object.entries(m).filter(([version]) => semver.satisfies(version, node)))
43+
44+
const matching = Object.entries(m).filter(([version]) => semver.satisfies(version, engines))
45+
46+
if (matching.length > 0) {
47+
m = Object.fromEntries(matching)
48+
}
49+
}
50+
3451
// If only latest major is true, filter out all but latest
3552
if (latestOfMajorOnly) {
3653
const vers = Object.values(m).reduce((latestMajor, v) => {

test/cli.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ suite('nv cli', () => {
4040
assert(semver.valid(r))
4141
})
4242
})
43+
4344
test('should only contain the latest of each major', () => {
4445
const result = execFileSync(nv, ['ls', '16.x || 18.x', '--no-pretty-json', '--latest-of-major-only'], { cwd })
4546
.toString().trim().split('\n')
@@ -50,4 +51,62 @@ suite('nv cli', () => {
5051
assert(result[0].version.startsWith('16.'))
5152
assert(result[1].version.startsWith('18.'))
5253
})
54+
55+
test('works with `--engines`', () => {
56+
const result = execFileSync(nv, ['ls', '8.x', '--only-version', '--engines=">=8"'], { cwd: path.join(__dirname, 'fixtures', 'engines') })
57+
.toString().trim().split('\n')
58+
59+
assert.deepEqual(result, [
60+
'8.10.0',
61+
'8.11.0',
62+
'8.11.1',
63+
'8.11.2',
64+
'8.11.3',
65+
'8.11.4',
66+
'8.12.0',
67+
'8.13.0',
68+
'8.14.0',
69+
'8.14.1',
70+
'8.15.0',
71+
'8.15.1',
72+
'8.16.0',
73+
'8.16.1',
74+
'8.16.2',
75+
'8.17.0'
76+
])
77+
78+
const result2 = execFileSync(nv, ['ls', '8.x', '--only-version', '--engines=">=8.15"'], { cwd: path.join(__dirname, 'fixtures', 'engines') })
79+
.toString().trim().split('\n')
80+
81+
assert.deepEqual(result2, [
82+
'8.15.0',
83+
'8.15.1',
84+
'8.16.0',
85+
'8.16.1',
86+
'8.16.2',
87+
'8.17.0'
88+
])
89+
90+
const result3 = execFileSync(nv, ['ls', '8.x', '--only-version', '--engines'], { cwd: path.join(__dirname, 'fixtures', 'engines') })
91+
.toString().trim().split('\n')
92+
93+
assert.deepEqual(result3, [
94+
'8.10.0',
95+
'8.11.0',
96+
'8.11.1',
97+
'8.11.2',
98+
'8.11.3',
99+
'8.11.4',
100+
'8.12.0',
101+
'8.13.0',
102+
'8.14.0',
103+
'8.14.1',
104+
'8.15.0',
105+
'8.15.1',
106+
'8.16.0',
107+
'8.16.1',
108+
'8.16.2',
109+
'8.17.0'
110+
])
111+
})
53112
})

test/fixtures/engines/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"engines": {
3+
"node": "^8.10"
4+
}
5+
}

test/index.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict'
22
const { suite, test } = require('mocha')
33
const assert = require('assert')
4+
const path = require('path')
45
const nv = require('..')
56

67
// 2019-02-07T16:15:49.683Z
@@ -209,4 +210,59 @@ suite('nv', () => {
209210
const versions = await nv('0.8.0', { now })
210211
assert.strictEqual(versions[0].codename, null)
211212
})
213+
214+
test('engines option', async () => {
215+
const versions = await nv('8.x', { now, cwd: path.join(__dirname, 'fixtures', 'engines'), engines: '>=8' })
216+
217+
assert.deepEqual(versions.map(x => x.version), [
218+
'8.10.0',
219+
'8.11.0',
220+
'8.11.1',
221+
'8.11.2',
222+
'8.11.3',
223+
'8.11.4',
224+
'8.12.0',
225+
'8.13.0',
226+
'8.14.0',
227+
'8.14.1',
228+
'8.15.0',
229+
'8.15.1',
230+
'8.16.0',
231+
'8.16.1',
232+
'8.16.2',
233+
'8.17.0'
234+
])
235+
236+
const versions2 = await nv('8.x', { now, cwd: path.join(__dirname, 'fixtures', 'engines'), engines: '>=8.15' })
237+
238+
assert.deepEqual(versions2.map(x => x.version), [
239+
'8.15.0',
240+
'8.15.1',
241+
'8.16.0',
242+
'8.16.1',
243+
'8.16.2',
244+
'8.17.0'
245+
])
246+
247+
const versions3 = await nv('8.x', { now, cwd: path.join(__dirname, 'fixtures', 'engines'), engines: true })
248+
249+
assert.deepEqual(versions3.map(x => x.version), [
250+
'8.10.0',
251+
'8.11.0',
252+
'8.11.1',
253+
'8.11.2',
254+
'8.11.3',
255+
'8.11.4',
256+
'8.12.0',
257+
'8.13.0',
258+
'8.14.0',
259+
'8.14.1',
260+
'8.15.0',
261+
'8.15.1',
262+
'8.16.0',
263+
'8.16.1',
264+
'8.16.2',
265+
'8.17.0'
266+
])
267+
})
212268
})

0 commit comments

Comments
 (0)