src/lib/cli/Command.js
/**
* A command that can be run through the CLI.
* @abstract
*/
export default class Command {
/**
* Creates a new Command with the given name and options.
* @param {string} name The command's name.
* @param {string} description The command's description.
* @param {Object} options The options to apply.
* @param {Map<string, Option>} options.options The options available for this command.
* @param {string} [options.arguments] The command's argument string. See yargs' documentation
* for details.
* @param {number} [options.minArguments] The minimum number or (non-option) arguments the command
* requires.
* @param {number} [options.maxArguments] The maximum number or (non-option) arguments the command
* requires.
* @param {boolean} [options.strict=true] Throw error for unknown arguments.
* @throws {Error} Throws an error if options.maxArguments is less than options.minArguments.
* @see {@link yargs}
*/
constructor(name, description, options = {}) {
/**
* The command's name.
* @type {String}
*/
this.name = name;
/**
* The command descriptions.
* @type {String}
*/
this.description = description;
if (
options.minArguments &&
options.maxArguments !== undefined &&
options.maxArguments < options.minArguments
) {
throw new Error('options.maxArguments must not be less than options.minArguments');
}
/**
* The command's raw options.
* @type {Object}
* @private
*/
this._options = options;
}
/**
* Runs the command with the current Cli instance. **Asynchronous commands should return a Promise
* here.**.
* @param {AtSCMCli} cli The current cli instance.
*/
// eslint-disable-next-line no-unused-vars
run(cli) {
throw new Error('Must be implemented by all subclasses');
}
/**
* Returns `true` if the command requires a {@link Liftoff.Environment} before it can be run.
* @param {AtSCMCli} cli The current cli instance.
* @return {boolean} `true` if the command requires a {@link Liftoff.Environment}.
*/
// eslint-disable-next-line no-unused-vars
requiresEnvironment(cli) {
return true;
}
/**
* Returns the usage string for the command. Something like "{name} {arguments}".
* @type {string}
*/
get usage() {
if (this._options.arguments) {
return `${this.name} ${this._options.arguments}`;
}
return this.name;
}
/**
* The options available for the command.
* @type {Map<string, Option>}
*/
get options() {
return this._options.options || {};
}
/**
* The minimum and maximum number of (non-option) arguments the command handles.
* @type {number[]}
*/
get demandCommand() {
const ret = [this._options.minArguments || 0];
if (this._options.maxArguments !== undefined) {
ret.push(this._options.maxArguments);
}
return ret;
}
/**
* If an error should be thrown for unknown arguments.
* @type {boolean}
*/
get strict() {
return this._options.strict !== undefined ? this._options.strict : true;
}
}