Skip to content

Commit

Permalink
feat: add support for building input form command line options
Browse files Browse the repository at this point in the history
  • Loading branch information
rossiam committed Aug 12, 2020
1 parent 1ad2162 commit 599c3c2
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 91 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ temp_notes.md
*.log
tsconfig.tsbuildinfo
scratch_pad.txt
packages/*/smartthings-cli-*.tgz
126 changes: 63 additions & 63 deletions packages/cli/README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/cli/src/commands/devices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { addLocationsAndRooms } from '../lib/api-helpers'
import { flags } from '@oclif/command'


export type DeviceWithLocation = DeviceListOptions & { location?: string }
export type DeviceWithLocation = Device & { location?: string }

export function buildTableOutput(this: APICommand, data: Device): string {
const table = this.tableGenerator.newOutputTable()
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/locations/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default class LocationsDeleteCommand extends SelectingAPICommand<Location

static args = [{
name: 'id',
description: 'location UUID or number in the list',
description: 'location id',
}]

primaryKeyName = 'locationId'
Expand Down
23 changes: 0 additions & 23 deletions packages/lib/src/api-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,26 +61,3 @@ export abstract class APICommand extends SmartThingsCommand {
{ urlProvider: this.clientIdProvider, logger })
}
}

/**
* TODO: most or all classes that use this should be updated soon to use
* `SelectingAPICommand` (or in a few cases `SelectingAPICommandBase`).
*/
export abstract class SimpleAPICommand extends APICommand {
/**
* This is just a convenience method that outputs a simple string message
* on success and handles exceptions. This is mostly useful for simple
* things like a DELETE call that don't have any complicated inputs or
* outputs.
*
* @param executeCommand function that does the work
*/
protected processNormally(successMessage: string, makeRequest: () => Promise<void>): void {
makeRequest().then(() => {
process.stdout.write(`${successMessage}\n`)
}).catch(err => {
this.logger.error(`caught error ${err}`)
this.exit(1)
})
}
}
40 changes: 37 additions & 3 deletions packages/lib/src/io-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ const outputFlag = {
export enum IOFormat {
YAML = 'yaml',
JSON = 'json',
// for input, this is Q & A, for output, it's a human-readable table format

// for input, this is Q & A or command line, for output, it's a human-readable table format
COMMON = 'common',
}

Expand Down Expand Up @@ -136,9 +137,36 @@ export abstract class Inputting<I> {
return this._inputOptions
}

/**
* Implement this method if you want to build input from command line
* options. If this method is implemented, one must also implement
* hasCommandLineInput.
*/
protected getInputFromCommandLine?(): Promise<I>

/**
* Implement this if and only if getInputFromCommandLine has been
* implemented. This should return true if command line arguments are
* present that can be used to construct the input.
*/
protected hasCommandLineInput?(): boolean

/**
* Implement this method if you want to be able to ask the user for input,
* usually in a question and answer format using inquirer.
*/
protected getInputFromUser?(): Promise<I>

protected async readInput(): Promise<I> {
if (this.hasCommandLineInput && this.hasCommandLineInput()) {
if (this.getInputFromCommandLine) {
return this.getInputFromCommandLine()
} else {
throw new Error('input is required either via' +
' file specified with --input option or from stdin')
}
}

if (this.inputOptions.format === IOFormat.COMMON && this.getInputFromUser) {
return this.getInputFromUser()
}
Expand Down Expand Up @@ -177,16 +205,22 @@ export abstract class Inputting<I> {

// eslint-disable-next-line @typescript-eslint/no-explicit-any
async setup(args: { [name: string]: any }, argv: string[], flags: { [name: string]: any }): Promise<void> {
const hasGetInputFromUser = this.getInputFromUser !== undefined
if (this.hasCommandLineInput !== undefined && this.getInputFromCommandLine === undefined
|| this.hasCommandLineInput === undefined && this.getInputFromCommandLine !== undefined) {
throw new Error('invalid code; implement both hasCommandLineInput and getInputFromCommandLine or neither')
}
let inputFormat: IOFormat
if (flags.json) {
inputFormat = IOFormat.JSON
} else if (flags.yaml) {
inputFormat = IOFormat.YAML
} else if (flags.input) {
inputFormat = formatFromFilename(flags.input)
} else if (this.getInputFromUser !== undefined && process.stdin.isTTY
|| this.hasCommandLineInput && this.hasCommandLineInput()) {
inputFormat = IOFormat.COMMON
} else {
inputFormat = hasGetInputFromUser && process.stdin.isTTY ? IOFormat.COMMON : IOFormat.YAML
inputFormat = IOFormat.YAML
}

this._inputOptions = {
Expand Down

0 comments on commit 599c3c2

Please sign in to comment.