feat(cli): parse options after dlx (#9735)

close  #9719
This commit is contained in:
Khải
2025-07-10 06:23:40 +07:00
committed by GitHub
parent 8bec871257
commit 6bcfa69964
5 changed files with 75 additions and 4 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/parse-cli-args": minor
"pnpm": patch
---
Allow `dlx` to parse CLI flags and options between the `dlx` command and the command to run or between the `dlx` command and `--` [#9719](https://github.com/pnpm/pnpm/issues/9719).

View File

@@ -108,8 +108,8 @@ export async function parseCliArgs (
return 'add'
}
function getEscapeArgsWithSpecialCaseForRun (): string[] | undefined {
if (cmd !== 'run') {
function getEscapeArgsWithSpecialCases (): string[] | undefined {
if (cmd !== 'run' && cmd !== 'dlx') {
return opts.escapeArgs
}
@@ -139,7 +139,7 @@ export async function parseCliArgs (
},
inputArgv,
0,
{ escapeArgs: getEscapeArgsWithSpecialCaseForRun() }
{ escapeArgs: getEscapeArgsWithSpecialCases() }
)
const workspaceDir = await getWorkspaceDir(options)

View File

@@ -336,3 +336,51 @@ test('should not swallows empty string in params', async () => {
expect(cmd).toBe('run')
expect(params).toStrictEqual(['echo', '', 'foo', '', 'bar'])
})
test('dlx parses CLI options in between "dlx" and the command name', async () => {
const { params, options, cmd } = await parseCliArgs({
...DEFAULT_OPTS,
}, [
'--reporter=append-only',
'dlx',
'--allow-build=some-package',
'--package=some-bin-package',
'some-command',
'--this-is-not-a-flag',
'another-argument',
])
expect(cmd).toBe('dlx')
expect(options).toStrictEqual({
reporter: 'append-only',
'allow-build': 'some-package',
package: 'some-bin-package',
})
expect(params).toStrictEqual([
'some-command',
'--this-is-not-a-flag',
'another-argument',
])
})
test('dlx stops parsing after "--"', async () => {
const { params, options, cmd } = await parseCliArgs({
...DEFAULT_OPTS,
}, [
'dlx',
'--package=some-package',
'--allow-build=foo',
'--allow-build=bar',
'--',
'--this-is-a-command',
'argument',
])
expect(cmd).toBe('dlx')
expect(options).toStrictEqual({
package: 'some-package',
'allow-build': ['foo', 'bar'],
})
expect(params).toStrictEqual([
'--this-is-a-command',
'argument',
])
})

View File

@@ -17,7 +17,7 @@ const RENAMED_OPTIONS = {
export async function parseCliArgs (inputArgv: string[]): Promise<ParsedCliArgs> {
return parseCliArgsLib({
fallbackCommand: 'run',
escapeArgs: ['create', 'dlx', 'exec', 'test'],
escapeArgs: ['create', 'exec', 'test'],
getCommandLongName: getCommandFullName,
getTypesByCommandName: getCliOptionsTypes,
renamedOptions: RENAMED_OPTIONS,

View File

@@ -18,6 +18,23 @@ beforeAll(async () => {
const createCacheKey = (...pkgs: string[]): string => dlx.createCacheKey(pkgs, registries)
test('dlx parses options between "dlx" and the command name', async () => {
prepareEmpty()
const global = path.resolve('..', 'global')
const pnpmHome = path.join(global, 'pnpm')
fs.mkdirSync(global)
const env = {
[PATH_NAME]: `${pnpmHome}${path.delimiter}${process.env[PATH_NAME]}`,
PNPM_HOME: pnpmHome,
XDG_DATA_HOME: global,
}
const result = execPnpmSync(['dlx', '--package', 'shx@0.3.4', '--silent', 'shx', 'echo', 'hi'], { env, expectSuccess: true })
expect(result.stdout.toString().trim()).toBe('hi')
})
test('silent dlx prints the output of the child process only', async () => {
prepare({})
const global = path.resolve('..', 'global')