feat: allow renaming of --json
jpshack-at-palomar opened this issue · comments
Problem
In our cli we have options for both input and output as JSON. The functionality provided by --json is great, but the flag name for us is ambiguous and we want to be able to override it. Furthermore we need --json as a modifier flag for commands that offer output options (e.g. --yaml vs. --json).
We've worked around this but our solution is quite hacky. A variation of the same problem is if one wanted to add additional information the definition of --json flag. That definition is hard-coded in aggregate-flags.ts and used in both the init time caching of commands (used by the help system) and during flag parsing.
Describe the solution you'd like
Open to many different ways of handling this:
a. Config parameter in package.json that allows overriding of the json flag name
b. Have aggregateFlags use a function rather than use its own constant to build the flag and allow commands to expose that function as a static method on the command class or in set in a hook.
c. Separate the runtime checks done against enableJsonFlag for error handling and logging from the definition of the flag itself and allow commands to manage this in their own init method.
d. remove the --jsonFlag if a command implements its own enableJsonFlag() method. (I think something like this worked some time back: #467)
Describe alternatives you've considered
Currently we are resorting to an ugly hack of setting our enableJsonFlag false on our base command and then flipping it to true in init. This ensures that the help-plugin doesn't list the --json flag but that error handling and output are handled correctly. This suggests to me that the framework is trying to do a little too much for me and that something along the lines of (c.) is likely better direction for oclif.
Additional context
I'd be happy to help with a PR if you'll indicate an acceptable direction.
@jpshack-at-palomar Let me make sure I understand your requirements:
- You want automatic json formatting for commands using a different flag that
--json
- You want a
--json
flag that doesn't trigger automatic json output
If that's the case, I'd suggest that this is something that you can achieve quite easily without any changes in oclif/core
import {Args, Command, Flags, Interfaces} from '@oclif/core'
export type Flags<T extends typeof Command> = Interfaces.InferredFlags<(typeof BaseCommand)['baseFlags'] & T['flags']>
export type Args<T extends typeof Command> = Interfaces.InferredArgs<T['args']>
abstract class BaseCommand<T extends typeof Command> extends Command {
static baseFlags = {
jsonOutput: Flags.boolean({
description: 'Output response in JSON format',
helpGroup: 'GLOBAL',
}),
}
protected args!: Args<T>
protected flags!: Flags<T>
public async init(): Promise<void> {
await super.init()
const {args, flags} = await this.parse({
args: this.ctor.args,
baseFlags: (super.ctor as typeof BaseCommand).baseFlags,
enableJsonFlag: this.ctor.enableJsonFlag,
flags: this.ctor.flags,
strict: this.ctor.strict,
})
this.flags = flags as Flags<T>
this.args = args as Args<T>
}
public jsonEnabled(): boolean {
// if --jsonOutput is set, return true
if (this.flags.jsonOutput) return true
// If the <CLI>_CONTENT_TYPE env var is set to json, return true
if (this.config.scopedEnvVar?.('CONTENT_TYPE')?.toLowerCase() === 'json') return true
return false
}
}
export default class Hello extends BaseCommand<typeof Hello> {
static args = {
person: Args.string({description: 'Person to say hello to', required: true}),
}
static flags = {
csv: Flags.boolean({description: 'Input CSV data'}),
from: Flags.string({char: 'f', description: 'Who is saying hello', required: true}),
json: Flags.boolean({description: 'Input JSON data'}),
yaml: Flags.boolean({description: 'Input YAML data'}),
}
async run(): Promise<{args: Args<typeof Hello>; flags: Flags<typeof Hello>}> {
this.log(`hello ${this.args.person} from ${this.flags.from}! (./src/commands/hello/index.ts)`)
return {args: this.args, flags: this.flags}
}
}
USAGE
$ gh1105 hello PERSON -f <value> [--jsonOutput] [--csv] [--json] [--yaml]
ARGUMENTS
PERSON Person to say hello to
FLAGS
-f, --from=<value> (required) Who is saying hello
--csv Input CSV data
--json Input JSON data
--yaml Input YAML data
GLOBAL FLAGS
--jsonOutput Output response in JSON format
COMMANDS
hello world Say hello world
By overriding the isJsonEnabled
method, you're able to get automatic json output using whatever flag name you want. You can see that you're now free to the --json
flag for other purposes.
Does that meet your requirements?
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.