Skip to content

Commit 1cd4eb0

Browse files
authored
feat(vite-node): make CLI arguments parsing behavior consistent with node/tsx/ts-node (#3574)
1 parent 3c85187 commit 1cd4eb0

File tree

3 files changed

+65
-4
lines changed

3 files changed

+65
-4
lines changed

packages/vite-node/src/cli.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,31 @@ import { installSourcemapsSupport } from './source-map'
1212
const cli = cac('vite-node')
1313

1414
cli
15-
.version(version)
1615
.option('-r, --root <path>', 'Use specified root directory')
1716
.option('-c, --config <path>', 'Use specified config file')
1817
.option('-m, --mode <mode>', 'Set env mode')
1918
.option('-w, --watch', 'Restart on file changes, similar to "nodemon"')
2019
.option('--script', 'Use vite-node as a script runner')
2120
.option('--options <options>', 'Use specified Vite server options')
22-
.help()
21+
.option('-v, --version', 'Output the version number')
22+
.option('-h, --help', 'Display help for command')
2323

2424
cli
2525
.command('[...files]')
2626
.allowUnknownOptions()
2727
.action(run)
2828

29-
cli.parse()
29+
cli.parse(process.argv, { run: false })
30+
31+
if (cli.args.length === 0) {
32+
cli.runMatchedCommand()
33+
}
34+
else {
35+
const i = cli.rawArgs.indexOf(cli.args[0]) + 1
36+
const scriptArgs = cli.rawArgs.slice(i).filter(it => it !== '--')
37+
const executeArgs = [...cli.rawArgs.slice(0, i), '--', ...scriptArgs]
38+
cli.parse(executeArgs)
39+
}
3040

3141
export interface CliOptions {
3242
root?: string
@@ -35,6 +45,8 @@ export interface CliOptions {
3545
mode?: string
3646
watch?: boolean
3747
options?: ViteNodeServerOptionsCLI
48+
version?: boolean
49+
help?: boolean
3850
'--'?: string[]
3951
}
4052

@@ -48,9 +60,18 @@ async function run(files: string[], options: CliOptions = {}) {
4860
process.argv = [...process.argv.slice(0, 2), ...(options['--'] || [])]
4961
}
5062

63+
if (options.version) {
64+
cli.version(version)
65+
cli.outputVersion()
66+
process.exit(0)
67+
}
68+
if (options.help) {
69+
cli.version(version).outputHelp()
70+
process.exit(0)
71+
}
5172
if (!files.length) {
5273
console.error(c.red('No files specified.'))
53-
cli.outputHelp()
74+
cli.version(version).outputHelp()
5475
process.exit(1)
5576
}
5677

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// eslint-disable-next-line no-console
2+
console.log(process.argv)

test/vite-node/test/cli.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { execa } from 'execa'
2+
import { resolve } from 'pathe'
3+
import { expect, it } from 'vitest'
4+
5+
const cliPath = resolve(__dirname, '../../../packages/vite-node/src/cli.ts')
6+
const entryPath = resolve(__dirname, '../src/cli-parse-args.js')
7+
8+
const parseResult = (s: string) => JSON.parse(s.replaceAll('\'', '"'))
9+
10+
it('basic', async () => {
11+
const result = await execa('npx', ['esno', cliPath, entryPath], { reject: true })
12+
expect(result.stdout).include('node')
13+
expect(parseResult(result.stdout)).length(2)
14+
}, 60_000)
15+
16+
it('--help', async () => {
17+
const r1 = await execa('npx', ['esno', cliPath, '--help', entryPath], { reject: true })
18+
expect(r1.stdout).include('help')
19+
const r2 = await execa('npx', ['esno', cliPath, '-h', entryPath], { reject: true })
20+
expect(r2.stdout).include('help')
21+
}, 60_000)
22+
23+
it('--version', async () => {
24+
const r1 = await execa('npx', ['esno', cliPath, '--version', entryPath], { reject: true })
25+
expect(r1.stdout).include('vite-node/')
26+
const r2 = await execa('npx', ['esno', cliPath, '-v', entryPath], { reject: true })
27+
expect(r2.stdout).include('vite-node/')
28+
}, 60_000)
29+
30+
it('script args', async () => {
31+
const r1 = await execa('npx', ['esno', cliPath, entryPath, '--version', '--help'], { reject: true })
32+
expect(parseResult(r1.stdout)).include('--version').include('--help')
33+
}, 60_000)
34+
35+
it('script args in -- after', async () => {
36+
const r1 = await execa('npx', ['esno', cliPath, entryPath, '--', '--version', '--help'], { reject: true })
37+
expect(parseResult(r1.stdout)).include('--version').include('--help')
38+
}, 60_000)

0 commit comments

Comments
 (0)