Custom Base Class
Use inheritance to share functionality between common commands. Here is an example of a command base class that has some common shared flags.
For large CLIs with multiple plugins, it's useful to put this base class into its own npm package to be shared.
// src/baseCommand.ts
import {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']>
export abstract class BaseCommand<T extends typeof Command> extends Command {
// add the --json flag
static enableJsonFlag = true
// define flags that can be inherited by any command that extends BaseCommand
static baseFlags = {
'log-level': Flags.option({
default: 'info',
helpGroup: 'GLOBAL',
options: ['debug', 'warn', 'error', 'info', 'trace'] as const,
summary: 'Specify level for logging.',
})(),
}
protected flags!: Flags<T>
protected args!: Args<T>
public async init(): Promise<void> {
await super.init()
const {args, flags} = await this.parse({
flags: this.ctor.flags,
baseFlags: (super.ctor as typeof BaseCommand).baseFlags,
enableJsonFlag: this.ctor.enableJsonFlag,
args: this.ctor.args,
strict: this.ctor.strict,
})
this.flags = flags as Flags<T>
this.args = args as Args<T>
}
protected async catch(err: Error & {exitCode?: number}): Promise<any> {
// add any custom logic to handle errors from the command
// or simply return the parent class error handling
return super.catch(err)
}
protected async finally(_: Error | undefined): Promise<any> {
// called after run and catch regardless of whether or not the command errored
return super.finally(_)
}
}
// src/commands/my-command.ts
export default class MyCommand extends BaseCommand<typeof MyCommand> {
static summary = 'child class that extends BaseCommand'
static examples = [
'<%= config.bin %> <%= command.id %>',
'<%= config.bin %> <%= command.id %> --json',
'<%= config.bin %> <%= command.id %> --log-level debug',
]
static flags = {
name: Flags.string({
char: 'n',
summary: 'Name to print.',
required: true,
}),
}
public async run(): Promise<Flags<typeof MyCommand>> {
for (const [flag, value] of Object.entries(this.flags)) {
this.log(`${flag}: ${value}`)
}
return this.flags
}
}
For a more complex example, here's how we do this for the Salesforce CLI.