1 parent
4f84d03914
commit
31d284337d
6 files changed
+58
-21
No files matched your search
@@ -3,9 +3,27 @@ import nopt = require('nopt')
|
||||
|
||||
const RECURSIVE_CMDS = new Set(['recursive', 'multi', 'm'])
|
||||
|
||||
export interface ParsedCliArgs {
|
||||
argv: {
|
||||
remain: string[],
|
||||
cooked: string[],
|
||||
original: string[],
|
||||
}
|
||||
cliArgs: string[]
|
||||
cliConf: {
|
||||
// tslint:disable-next-line: no-any
|
||||
[option: string]: any,
|
||||
}
|
||||
cmd: string | null
|
||||
subCmd: string | null
|
||||
isKnownCommand: boolean
|
||||
unknownOptions: string[]
|
||||
workspaceDir?: string
|
||||
}
|
||||
|
||||
export default async function parseCliArgs (
|
||||
opts: {
|
||||
getCommandLongName: (commandName: string) => string,
|
||||
getCommandLongName: (commandName: string) => string | null,
|
||||
getTypesByCommandName: (commandName: string) => object,
|
||||
globalOptionsTypes: Record<string, unknown>,
|
||||
isKnownCommand: (commandName: string) => boolean,
|
||||
@@ -13,7 +31,7 @@ export default async function parseCliArgs (
|
||||
shortHands: Record<string, string>,
|
||||
},
|
||||
inputArgv: string[],
|
||||
) {
|
||||
): Promise<ParsedCliArgs> {
|
||||
const noptExploratoryResults = nopt(
|
||||
{
|
||||
filter: [String],
|
||||
@@ -36,7 +54,7 @@ export default async function parseCliArgs (
|
||||
cliArgs: noptExploratoryResults.argv.remain,
|
||||
cliConf: {},
|
||||
cmd: 'help',
|
||||
dir: process.cwd(),
|
||||
isKnownCommand: true,
|
||||
subCmd: null,
|
||||
unknownOptions: [] as string[],
|
||||
}
|
||||
@@ -67,9 +85,10 @@ export default async function parseCliArgs (
|
||||
}
|
||||
}
|
||||
|
||||
let cmd = opts.getCommandLongName(argv.remain[0])
|
||||
let cmd = argv.remain.length > 0 ? opts.getCommandLongName(argv.remain[0]) : null
|
||||
let isKnownCommand = true
|
||||
if (cmd && !opts.isKnownCommand(cmd) && !RECURSIVE_CMDS.has(cmd)) {
|
||||
cmd = 'help'
|
||||
isKnownCommand = false
|
||||
}
|
||||
|
||||
let subCmd: string | null = argv.remain[1] && opts.getCommandLongName(argv.remain[1])
|
||||
@@ -77,9 +96,9 @@ export default async function parseCliArgs (
|
||||
// `pnpm install ""` is going to be just `pnpm install`
|
||||
const cliArgs = argv.remain.slice(1).filter(Boolean)
|
||||
|
||||
if (cliConf['recursive'] !== true && (cliConf['filter'] || RECURSIVE_CMDS.has(cmd))) {
|
||||
if (cliConf['recursive'] !== true && (cliConf['filter'] || RECURSIVE_CMDS.has(cmd!))) {
|
||||
cliConf['recursive'] = true
|
||||
if (subCmd && RECURSIVE_CMDS.has(cmd)) {
|
||||
if (subCmd && RECURSIVE_CMDS.has(cmd!)) {
|
||||
cliArgs.shift()
|
||||
argv.remain.shift()
|
||||
cmd = subCmd
|
||||
@@ -119,6 +138,7 @@ export default async function parseCliArgs (
|
||||
cliArgs,
|
||||
cliConf,
|
||||
cmd,
|
||||
isKnownCommand,
|
||||
subCmd,
|
||||
unknownOptions,
|
||||
workspaceDir,
|
||||
|
||||
@@ -85,13 +85,14 @@ test('when runnning a global command inside a workspace, the workspace should be
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('help is returned when an unknown command is used', async (t) => {
|
||||
const { cmd } = await parseCliArgs({
|
||||
test('isKnownCommand is false when an unknown command is used', async (t) => {
|
||||
const { cmd, isKnownCommand } = await parseCliArgs({
|
||||
...DEFAULT_OPTS,
|
||||
globalOptionsTypes: {},
|
||||
isKnownCommand: () => false,
|
||||
}, ['foo'])
|
||||
t.equal(cmd, 'help')
|
||||
t.false(isKnownCommand)
|
||||
t.equal(cmd, 'foo')
|
||||
t.end()
|
||||
})
|
||||
|
||||
@@ -166,9 +167,10 @@ test('if a help option is used, set cmd to "help"', async (t) => {
|
||||
})
|
||||
|
||||
test('no command', async (t) => {
|
||||
const { cmd } = await parseCliArgs({
|
||||
const { cmd, isKnownCommand } = await parseCliArgs({
|
||||
...DEFAULT_OPTS,
|
||||
}, ['--version'])
|
||||
t.equal(cmd, undefined)
|
||||
t.equal(cmd, null)
|
||||
t.true(isKnownCommand)
|
||||
t.end()
|
||||
})
|
||||
@@ -130,8 +130,8 @@ export function getCliOptionsTypes (commandName: string) {
|
||||
return cliOptionsTypesByCommandName[commandName]?.() || {}
|
||||
}
|
||||
|
||||
export function getRCOptionsTypes (commandName: string) {
|
||||
return rcOptionsTypesByCommandName[commandName]?.() || {}
|
||||
export function getRCOptionsTypes (commandName: string | null) {
|
||||
return (commandName && rcOptionsTypesByCommandName[commandName]?.()) || {}
|
||||
}
|
||||
|
||||
export function getCommandFullName (commandName: string) {
|
||||
|
||||
@@ -30,7 +30,13 @@ import parseCliArgs from './parseCliArgs'
|
||||
import initReporter, { ReporterType } from './reporter'
|
||||
|
||||
export default async function run (inputArgv: string[]) {
|
||||
const { argv, cliArgs, cliConf, cmd, subCmd, unknownOptions, workspaceDir } = await parseCliArgs(inputArgv)
|
||||
const { argv, cliArgs, cliConf, cmd, subCmd, isKnownCommand, unknownOptions, workspaceDir } = await parseCliArgs(inputArgv)
|
||||
if (!isKnownCommand) {
|
||||
console.error(`${chalk.bgRed.black('\u2009ERROR\u2009')} ${chalk.red(`Unknown command '${cmd}'`)}`)
|
||||
console.log(`For help, run: pnpm help`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (unknownOptions.length > 0) {
|
||||
let errorMsg = `${chalk.bgRed.black('\u2009ERROR\u2009')}`
|
||||
if (unknownOptions.length === 1) {
|
||||
@@ -39,7 +45,7 @@ export default async function run (inputArgv: string[]) {
|
||||
errorMsg += ` ${chalk.red(`Unknown options ${unknownOptions.map(unknownOption => `'${unknownOption}'`).join(', ')}`)}`
|
||||
}
|
||||
console.error(errorMsg)
|
||||
console.log(`For help, run: pnpm help ${cmd}`)
|
||||
console.log(`For help, run: pnpm help${cmd ? ` ${cmd}` : ''}`)
|
||||
process.exit(1)
|
||||
}
|
||||
process.env['npm_config_argv'] = JSON.stringify(argv)
|
||||
@@ -59,7 +65,7 @@ export default async function run (inputArgv: string[]) {
|
||||
} catch (err) {
|
||||
// Reporting is not initialized at this point, so just printing the error
|
||||
console.error(`${chalk.bgRed.black('\u2009ERROR\u2009')} ${chalk.red(err.message)}`)
|
||||
console.log(`For help, run: pnpm help ${cmd}`)
|
||||
console.log(`For help, run: pnpm help${cmd ? ` ${cmd}` : ''}`)
|
||||
process.exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export type ReporterType = 'default' | 'ndjson' | 'silent' | 'append-only'
|
||||
export default (
|
||||
reporterType: ReporterType,
|
||||
opts: {
|
||||
cmd: string,
|
||||
cmd: string | null,
|
||||
subCmd: string | null,
|
||||
config: Config,
|
||||
},
|
||||
@@ -17,7 +17,7 @@ export default (
|
||||
case 'default':
|
||||
defaultReporter({
|
||||
context: {
|
||||
argv: opts.subCmd ? [opts.cmd, opts.subCmd] : [opts.cmd],
|
||||
argv: opts.cmd ? opts.subCmd ? [opts.cmd, opts.subCmd] : [opts.cmd] : [],
|
||||
config: opts.config,
|
||||
},
|
||||
reportingOptions: {
|
||||
@@ -30,7 +30,7 @@ export default (
|
||||
case 'append-only':
|
||||
defaultReporter({
|
||||
context: {
|
||||
argv: opts.subCmd ? [opts.cmd, opts.subCmd] : [opts.cmd],
|
||||
argv: opts.cmd ? opts.subCmd ? [opts.cmd, opts.subCmd] : [opts.cmd] : [],
|
||||
config: opts.config,
|
||||
},
|
||||
reportingOptions: {
|
||||
|
||||
@@ -67,7 +67,16 @@ test('pass through to npm with all the args', async t => {
|
||||
t.equal(result.status, 0, 'command was successfull')
|
||||
})
|
||||
|
||||
test('command fails when unsupport flag is used', async (t) => {
|
||||
test('pnpm fails when an unsupported command is used', async (t) => {
|
||||
const project = prepare(t)
|
||||
|
||||
const { status, stderr } = execPnpmSync('unsupported-command')
|
||||
|
||||
t.equal(status, 1, 'command failed')
|
||||
t.ok(stderr.toString().includes("Unknown command 'unsupported-command'"))
|
||||
})
|
||||
|
||||
test('command fails when an unsupported flag is used', async (t) => {
|
||||
const project = prepare(t)
|
||||
|
||||
const { status, stderr } = execPnpmSync('update', '--save-dev')
|
||||
|
||||
Reference in new issue
Block a user