Skip to content

Commit

Permalink
feat(cli): validate option flags
Browse files Browse the repository at this point in the history
  • Loading branch information
eysi09 committed May 27, 2018
1 parent a64fbb0 commit 8c249bd
Showing 1 changed file with 23 additions and 4 deletions.
27 changes: 23 additions & 4 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
shutdown,
sleep,
} from "./util"
import { merge, intersection, reduce } from "lodash"
import { difference, flatten, merge, intersection, reduce } from "lodash"
import {
BooleanParameter,
Command,
Expand Down Expand Up @@ -195,6 +195,11 @@ function makeOptConfig(param: Parameter<any>): OptConfig {
return config
}

function getAliases(params: ParameterValues<any>) {
return flatten(Object.entries(params)
.map(([key, param]) => param.alias ? [key, param.alias] : [key]))
}

/**
* Returns the params that need to be overridden set to false
*/
Expand Down Expand Up @@ -240,7 +245,7 @@ export class GardenCli {
implicitCommand: false,
})
.showHelpByDefault()
.check((argv, _context) => {
.check((argv, _ctx) => {
// NOTE: Need to mutate argv!
merge(argv, falsifyConflictingParams(argv, GLOBAL_OPTIONS))
})
Expand All @@ -263,6 +268,7 @@ export class GardenCli {
new TestCommand(),
new ValidateCommand(),
]

const globalOptions = Object.entries(GLOBAL_OPTIONS)

commands.forEach(command => this.addCommand(command, this.program))
Expand All @@ -286,8 +292,8 @@ export class GardenCli {

this.commands[fullName] = command

const args = command.arguments as Parameter<any>
const options = command.options as Parameter<any>
const args = <ParameterValues<any>>command.arguments || {}
const options = <ParameterValues<any>>command.options || {}
const subCommands = command.subCommands || []
const argKeys = getKeys(args)
const optKeys = getKeys(options)
Expand All @@ -305,6 +311,19 @@ export class GardenCli {
const root = resolve(process.cwd(), optsForAction.root)
const env = optsForAction.env

// Validate options (feels like the parser should handle this)

This comment has been minimized.

Copy link
@edvald

edvald May 28, 2018

Collaborator

The docs mention an 'unknown' type, which isn't further documented but a search in the sywac code could provide some clues... Maybe that would be more clean?

This comment has been minimized.

Copy link
@eysi09

eysi09 May 28, 2018

Author Collaborator

Yeah I left an issue on their Github page and was told that there's no idiomatic way to this with the current API (sywac/sywac#17).

First of all the check needs to be at the command level because in the check function provided by the API it's not obvious which command was called unless we do the parsing ourselves which kind of beats the purpose of having a cli parser.

Second, it's not obvious from the clicContext object which input string is what (command name, positional argument, option, etc), so there we actually do need to the parsing ourselves.

This comment has been minimized.

Copy link
@edvald

edvald May 28, 2018

Collaborator

Got it. Oh well.

const builtinOptions = ["help", "h", "version", "v"]
const availableOptions = [...getAliases(options), ...getAliases(GLOBAL_OPTIONS), ...builtinOptions]
const passedOptions = cliContext.args
.filter(str => str.startsWith("-") || str.startsWith("--"))
.map(str => str.startsWith("--") ? str.slice(2) : str.slice(1))
.map(str => str.split("=")[0])
const invalid = difference(passedOptions, availableOptions)
if (invalid.length > 0) {
cliContext.cliMessage(`Received invalid flag(s): ${invalid.join(" ")}`)
return
}

// Configure logger
const logger = this.logger
const { loglevel, silent, output } = optsForAction
Expand Down

0 comments on commit 8c249bd

Please sign in to comment.