Socket
Socket
Sign inDemoInstall

clipanion

Package Overview
Dependencies
Maintainers
1
Versions
84
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

clipanion - npm Package Compare versions

Comparing version 2.4.1 to 2.4.2

4

lib/index.d.ts
/// <reference types="node" />
/// <reference types="mocha" />
import { Readable, Writable } from "stream";

@@ -50,3 +49,2 @@ // ------------------------------------------------------------------------

// @ts-ignore
// @ts-ignore
declare const reducers: {

@@ -450,3 +448,3 @@ setCandidateUsage: (state: RunState, segment: string, usage: string) => {

static from<Context extends BaseContext = BaseContext>(commandClasses: CommandClass<Context>[]): Cli<Context>;
constructor({ binaryLabel, binaryName$0, binaryVersion, enableColors }?: {
constructor({ binaryLabel, binaryName: binaryNameOpt, binaryVersion, enableColors }?: {
binaryLabel?: string;

@@ -453,0 +451,0 @@ binaryName?: string;

@@ -5,125 +5,93 @@ 'use strict';

let Command = /** @class */ (() => {
class Command {
constructor() {
/**
* Predefined that will be set to true if `-h,--help` has been used, in which case `Command#execute` shouldn't be called.
*/
this.help = false;
}
static getMeta(prototype) {
const base = prototype.constructor;
return base.meta = Object.prototype.hasOwnProperty.call(base, `meta`) ? base.meta : {
definitions: [],
transformers: [
(state, command) => {
for (const { name, value } of state.options) {
if (name === `-h` || name === `--help`) {
// @ts-ignore: The property is meant to have been defined by the child class
command.help = value;
}
}
},
],
};
}
static resolveMeta(prototype) {
const definitions = [];
const transformers = [];
for (let proto = prototype; proto instanceof Command; proto = proto.__proto__) {
const meta = this.getMeta(proto);
for (const definition of meta.definitions)
definitions.push(definition);
for (const transformer of meta.transformers) {
transformers.push(transformer);
}
}
return {
definitions,
transformers,
};
}
static registerDefinition(prototype, definition) {
this.getMeta(prototype).definitions.push(definition);
}
static registerTransformer(prototype, transformer) {
this.getMeta(prototype).transformers.push(transformer);
}
static addPath(...path) {
this.Path(...path)(this.prototype, `execute`);
}
static addOption(name, builder) {
builder(this.prototype, name);
}
class Command {
constructor() {
/**
* Wrap the specified command to be attached to the given path on the command line.
* The first path thus attached will be considered the "main" one, and all others will be aliases.
* @param path The command path.
* Predefined that will be set to true if `-h,--help` has been used, in which case `Command#execute` shouldn't be called.
*/
static Path(...path) {
return (prototype, propertyName) => {
this.registerDefinition(prototype, command => {
command.addPath(path);
});
};
}
/**
* Register a boolean listener for the given option names. When Clipanion detects that this argument is present, the value will be set to false. The value won't be set unless the option is found, so you must remember to set it to an appropriate default value.
* @param descriptor the option names.
*/
static Boolean(descriptor, { hidden = false } = {}) {
return (prototype, propertyName) => {
const optNames = descriptor.split(`,`);
this.registerDefinition(prototype, command => {
command.addOption({ names: optNames, arity: 0, hidden, allowBinding: false });
});
this.registerTransformer(prototype, (state, command) => {
this.help = false;
}
static getMeta(prototype) {
const base = prototype.constructor;
return base.meta = Object.prototype.hasOwnProperty.call(base, `meta`) ? base.meta : {
definitions: [],
transformers: [
(state, command) => {
for (const { name, value } of state.options) {
if (optNames.includes(name)) {
if (name === `-h` || name === `--help`) {
// @ts-ignore: The property is meant to have been defined by the child class
command[propertyName] = value;
command.help = value;
}
}
});
};
},
],
};
}
static resolveMeta(prototype) {
const definitions = [];
const transformers = [];
for (let proto = prototype; proto instanceof Command; proto = proto.__proto__) {
const meta = this.getMeta(proto);
for (const definition of meta.definitions)
definitions.push(definition);
for (const transformer of meta.transformers) {
transformers.push(transformer);
}
}
static String(descriptor = { required: true }, { tolerateBoolean = false, hidden = false } = {}) {
return (prototype, propertyName) => {
if (typeof descriptor === `string`) {
const optNames = descriptor.split(`,`);
this.registerDefinition(prototype, command => {
// If tolerateBoolean is specified, the command will only accept a string value
// using the bind syntax and will otherwise act like a boolean option
command.addOption({ names: optNames, arity: tolerateBoolean ? 0 : 1, hidden });
});
this.registerTransformer(prototype, (state, command) => {
for (const { name, value } of state.options) {
if (optNames.includes(name)) {
// @ts-ignore: The property is meant to have been defined by the child class
command[propertyName] = value;
}
}
});
return {
definitions,
transformers,
};
}
static registerDefinition(prototype, definition) {
this.getMeta(prototype).definitions.push(definition);
}
static registerTransformer(prototype, transformer) {
this.getMeta(prototype).transformers.push(transformer);
}
static addPath(...path) {
this.Path(...path)(this.prototype, `execute`);
}
static addOption(name, builder) {
builder(this.prototype, name);
}
/**
* Wrap the specified command to be attached to the given path on the command line.
* The first path thus attached will be considered the "main" one, and all others will be aliases.
* @param path The command path.
*/
static Path(...path) {
return (prototype, propertyName) => {
this.registerDefinition(prototype, command => {
command.addPath(path);
});
};
}
/**
* Register a boolean listener for the given option names. When Clipanion detects that this argument is present, the value will be set to false. The value won't be set unless the option is found, so you must remember to set it to an appropriate default value.
* @param descriptor the option names.
*/
static Boolean(descriptor, { hidden = false } = {}) {
return (prototype, propertyName) => {
const optNames = descriptor.split(`,`);
this.registerDefinition(prototype, command => {
command.addOption({ names: optNames, arity: 0, hidden, allowBinding: false });
});
this.registerTransformer(prototype, (state, command) => {
for (const { name, value } of state.options) {
if (optNames.includes(name)) {
// @ts-ignore: The property is meant to have been defined by the child class
command[propertyName] = value;
}
}
else {
this.registerDefinition(prototype, command => {
command.addPositional({ name: propertyName, required: descriptor.required });
});
this.registerTransformer(prototype, (state, command) => {
if (state.positionals.length > 0) {
// @ts-ignore: The property is meant to have been defined by the child class
command[propertyName] = state.positionals.shift().value;
}
});
}
};
}
/**
* Register a listener that looks for an option and its followup argument. When Clipanion detects that this argument is present, the value will be pushed into the array represented in the property.
*/
static Array(descriptor, { hidden = false } = {}) {
return (prototype, propertyName) => {
});
};
}
static String(descriptor = { required: true }, { tolerateBoolean = false, hidden = false } = {}) {
return (prototype, propertyName) => {
if (typeof descriptor === `string`) {
const optNames = descriptor.split(`,`);
this.registerDefinition(prototype, command => {
command.addOption({ names: optNames, arity: 1, hidden });
// If tolerateBoolean is specified, the command will only accept a string value
// using the bind syntax and will otherwise act like a boolean option
command.addOption({ names: optNames, arity: tolerateBoolean ? 0 : 1, hidden });
});

@@ -134,84 +102,113 @@ this.registerTransformer(prototype, (state, command) => {

// @ts-ignore: The property is meant to have been defined by the child class
command[propertyName] = command[propertyName] || [];
// @ts-ignore: The property is meant to have been defined by the child class
command[propertyName].push(value);
command[propertyName] = value;
}
}
});
};
}
static Rest({ required = 0 } = {}) {
return (prototype, propertyName) => {
}
else {
this.registerDefinition(prototype, command => {
command.addRest({ name: propertyName, required });
command.addPositional({ name: propertyName, required: descriptor.required });
});
this.registerTransformer(prototype, (state, command) => {
// @ts-ignore: The property is meant to have been defined by the child class
command[propertyName] = state.positionals.map(({ value }) => value);
if (state.positionals.length > 0) {
// @ts-ignore: The property is meant to have been defined by the child class
command[propertyName] = state.positionals.shift().value;
}
});
};
}
/**
* Register a listener that takes all the arguments remaining (including options and such) and store them into the selected property.
* Note that all methods affecting positional arguments are evaluated in the definition order; don't mess with it (for example sorting your properties in ascendent order might have adverse results).
*/
static Proxy({ required = 0 } = {}) {
return (prototype, propertyName) => {
this.registerDefinition(prototype, command => {
command.addProxy({ required });
});
this.registerTransformer(prototype, (state, command) => {
// @ts-ignore: The property is meant to have been defined by the child class
command[propertyName] = state.positionals.map(({ value }) => value);
});
};
}
/**
* Defines the usage information for the given command.
* @param usage
*/
static Usage(usage) {
return usage;
}
/**
* Defines the schema for the given command.
* @param schema
*/
static Schema(schema) {
return schema;
}
async validateAndExecute() {
const commandClass = this.constructor;
const schema = commandClass.schema;
if (typeof schema !== `undefined`) {
try {
await schema.validate(this);
}
};
}
/**
* Register a listener that looks for an option and its followup argument. When Clipanion detects that this argument is present, the value will be pushed into the array represented in the property.
*/
static Array(descriptor, { hidden = false } = {}) {
return (prototype, propertyName) => {
const optNames = descriptor.split(`,`);
this.registerDefinition(prototype, command => {
command.addOption({ names: optNames, arity: 1, hidden });
});
this.registerTransformer(prototype, (state, command) => {
for (const { name, value } of state.options) {
if (optNames.includes(name)) {
// @ts-ignore: The property is meant to have been defined by the child class
command[propertyName] = command[propertyName] || [];
// @ts-ignore: The property is meant to have been defined by the child class
command[propertyName].push(value);
}
}
catch (error) {
if (error.name === `ValidationError`)
error.clipanion = { type: `usage` };
throw error;
}
});
};
}
static Rest({ required = 0 } = {}) {
return (prototype, propertyName) => {
this.registerDefinition(prototype, command => {
command.addRest({ name: propertyName, required });
});
this.registerTransformer(prototype, (state, command) => {
// @ts-ignore: The property is meant to have been defined by the child class
command[propertyName] = state.positionals.map(({ value }) => value);
});
};
}
/**
* Register a listener that takes all the arguments remaining (including options and such) and store them into the selected property.
* Note that all methods affecting positional arguments are evaluated in the definition order; don't mess with it (for example sorting your properties in ascendent order might have adverse results).
*/
static Proxy({ required = 0 } = {}) {
return (prototype, propertyName) => {
this.registerDefinition(prototype, command => {
command.addProxy({ required });
});
this.registerTransformer(prototype, (state, command) => {
// @ts-ignore: The property is meant to have been defined by the child class
command[propertyName] = state.positionals.map(({ value }) => value);
});
};
}
/**
* Defines the usage information for the given command.
* @param usage
*/
static Usage(usage) {
return usage;
}
/**
* Defines the schema for the given command.
* @param schema
*/
static Schema(schema) {
return schema;
}
async validateAndExecute() {
const commandClass = this.constructor;
const schema = commandClass.schema;
if (typeof schema !== `undefined`) {
try {
await schema.validate(this);
}
const exitCode = await this.execute();
if (typeof exitCode !== `undefined`) {
return exitCode;
catch (error) {
if (error.name === `ValidationError`)
error.clipanion = { type: `usage` };
throw error;
}
else {
return 0;
}
}
const exitCode = await this.execute();
if (typeof exitCode !== `undefined`) {
return exitCode;
}
else {
return 0;
}
}
/**
* A list of useful semi-opinionated command entries that have to be registered manually.
*
* They cover the basic needs of most CLIs (e.g. help command, version command).
*
* @example
* cli.register(Command.Entries.Help);
* cli.register(Command.Entries.Version);
*/
Command.Entries = {};
return Command;
})();
}
/**
* A list of useful semi-opinionated command entries that have to be registered manually.
*
* They cover the basic needs of most CLIs (e.g. help command, version command).
*
* @example
* cli.register(Command.Entries.Help);
* cli.register(Command.Entries.Version);
*/
Command.Entries = {};

@@ -240,28 +237,22 @@ /*! *****************************************************************************

let HelpCommand = /** @class */ (() => {
class HelpCommand extends Command {
async execute() {
this.context.stdout.write(this.cli.usage(null));
}
class HelpCommand extends Command {
async execute() {
this.context.stdout.write(this.cli.usage(null));
}
__decorate([
Command.Path(`--help`),
Command.Path(`-h`)
], HelpCommand.prototype, "execute", null);
return HelpCommand;
})();
}
__decorate([
Command.Path(`--help`),
Command.Path(`-h`)
], HelpCommand.prototype, "execute", null);
let VersionCommand = /** @class */ (() => {
class VersionCommand extends Command {
async execute() {
var _a;
this.context.stdout.write(`${(_a = this.cli.binaryVersion) !== null && _a !== void 0 ? _a : `<unknown>`}\n`);
}
class VersionCommand extends Command {
async execute() {
var _a;
this.context.stdout.write(`${(_a = this.cli.binaryVersion) !== null && _a !== void 0 ? _a : `<unknown>`}\n`);
}
__decorate([
Command.Path(`--version`),
Command.Path(`-v`)
], VersionCommand.prototype, "execute", null);
return VersionCommand;
})();
}
__decorate([
Command.Path(`--version`),
Command.Path(`-v`)
], VersionCommand.prototype, "execute", null);

@@ -1146,279 +1137,276 @@ const NODE_INITIAL = 0;

*/
let Cli = /** @class */ (() => {
class Cli {
constructor({ binaryLabel, binaryName = `...`, binaryVersion, enableColors = getDefaultColorSettings() } = {}) {
this.registrations = new Map();
this.builder = new CliBuilder({ binaryName });
this.binaryLabel = binaryLabel;
this.binaryName = binaryName;
this.binaryVersion = binaryVersion;
this.enableColors = enableColors;
class Cli {
constructor({ binaryLabel, binaryName: binaryNameOpt = `...`, binaryVersion, enableColors = getDefaultColorSettings() } = {}) {
this.registrations = new Map();
this.builder = new CliBuilder({ binaryName: binaryNameOpt });
this.binaryLabel = binaryLabel;
this.binaryName = binaryNameOpt;
this.binaryVersion = binaryVersion;
this.enableColors = enableColors;
}
/**
* Creates a new Cli and registers all commands passed as parameters.
*
* @param commandClasses The Commands to register
* @returns The created `Cli` instance
*/
static from(commandClasses) {
const cli = new Cli();
for (const commandClass of commandClasses)
cli.register(commandClass);
return cli;
}
/**
* Registers a command inside the CLI.
*/
register(commandClass) {
const commandBuilder = this.builder.command();
this.registrations.set(commandClass, commandBuilder.cliIndex);
const { definitions } = commandClass.resolveMeta(commandClass.prototype);
for (const definition of definitions)
definition(commandBuilder);
commandBuilder.setContext({
commandClass,
});
}
process(input) {
const { contexts, process } = this.builder.compile();
const state = process(input);
switch (state.selectedIndex) {
case HELP_COMMAND_INDEX:
{
return HelpCommand$1.from(state, this, contexts);
}
default:
{
const { commandClass } = contexts[state.selectedIndex];
const command = new commandClass();
command.path = state.path;
const { transformers } = commandClass.resolveMeta(commandClass.prototype);
for (const transformer of transformers)
transformer(state, command);
return command;
}
}
/**
* Creates a new Cli and registers all commands passed as parameters.
*
* @param commandClasses The Commands to register
* @returns The created `Cli` instance
*/
static from(commandClasses) {
const cli = new Cli();
for (const commandClass of commandClasses)
cli.register(commandClass);
return cli;
}
async run(input, context) {
let command;
if (!Array.isArray(input)) {
command = input;
}
/**
* Registers a command inside the CLI.
*/
register(commandClass) {
const commandBuilder = this.builder.command();
this.registrations.set(commandClass, commandBuilder.cliIndex);
const { definitions } = commandClass.resolveMeta(commandClass.prototype);
for (const definition of definitions)
definition(commandBuilder);
commandBuilder.setContext({
commandClass,
});
}
process(input) {
const { contexts, process } = this.builder.compile();
const state = process(input);
switch (state.selectedIndex) {
case HELP_COMMAND_INDEX:
{
return HelpCommand$1.from(state, this, contexts);
}
default:
{
const { commandClass } = contexts[state.selectedIndex];
const command = new commandClass();
command.path = state.path;
const { transformers } = commandClass.resolveMeta(commandClass.prototype);
for (const transformer of transformers)
transformer(state, command);
return command;
}
}
}
async run(input, context) {
let command;
if (!Array.isArray(input)) {
command = input;
}
else {
try {
command = this.process(input);
}
catch (error) {
context.stdout.write(this.error(error));
return 1;
}
}
if (command.help) {
context.stdout.write(this.usage(command, { detailed: true }));
return 0;
}
command.context = context;
command.cli = {
binaryLabel: this.binaryLabel,
binaryName: this.binaryName,
binaryVersion: this.binaryVersion,
definitions: () => this.definitions(),
error: (error, opts) => this.error(error, opts),
process: input => this.process(input),
run: (input, subContext) => this.run(input, Object.assign(Object.assign({}, context), subContext)),
usage: (command, opts) => this.usage(command, opts),
};
let exitCode;
else {
try {
exitCode = await command.validateAndExecute();
command = this.process(input);
}
catch (error) {
context.stdout.write(this.error(error, { command }));
context.stdout.write(this.error(error));
return 1;
}
return exitCode;
}
/**
* Runs a command and exits the current `process` with the exit code returned by the command.
*
* @param input An array containing the name of the command and its arguments.
*
* @example
* cli.runExit(process.argv.slice(2), Cli.defaultContext)
*/
async runExit(input, context) {
process.exitCode = await this.run(input, context);
if (command.help) {
context.stdout.write(this.usage(command, { detailed: true }));
return 0;
}
suggest(input, partial) {
const { contexts, process, suggest } = this.builder.compile();
return suggest(input, partial);
command.context = context;
command.cli = {
binaryLabel: this.binaryLabel,
binaryName: this.binaryName,
binaryVersion: this.binaryVersion,
definitions: () => this.definitions(),
error: (error, opts) => this.error(error, opts),
process: input => this.process(input),
run: (input, subContext) => this.run(input, Object.assign(Object.assign({}, context), subContext)),
usage: (command, opts) => this.usage(command, opts),
};
let exitCode;
try {
exitCode = await command.validateAndExecute();
}
definitions({ colored = false } = {}) {
const data = [];
for (const [commandClass, number] of this.registrations) {
catch (error) {
context.stdout.write(this.error(error, { command }));
return 1;
}
return exitCode;
}
/**
* Runs a command and exits the current `process` with the exit code returned by the command.
*
* @param input An array containing the name of the command and its arguments.
*
* @example
* cli.runExit(process.argv.slice(2), Cli.defaultContext)
*/
async runExit(input, context) {
process.exitCode = await this.run(input, context);
}
suggest(input, partial) {
const { contexts, process, suggest } = this.builder.compile();
return suggest(input, partial);
}
definitions({ colored = false } = {}) {
const data = [];
for (const [commandClass, number] of this.registrations) {
if (typeof commandClass.usage === `undefined`)
continue;
const path = this.getUsageByIndex(number, { detailed: false });
const usage = this.getUsageByIndex(number, { detailed: true });
const category = typeof commandClass.usage.category !== `undefined`
? formatMarkdownish(commandClass.usage.category, { format: this.format(colored), paragraphs: false })
: undefined;
const description = typeof commandClass.usage.description !== `undefined`
? formatMarkdownish(commandClass.usage.description, { format: this.format(colored), paragraphs: false })
: undefined;
const details = typeof commandClass.usage.details !== `undefined`
? formatMarkdownish(commandClass.usage.details, { format: this.format(colored), paragraphs: true })
: undefined;
const examples = typeof commandClass.usage.examples !== `undefined`
? commandClass.usage.examples.map(([label, cli]) => [formatMarkdownish(label, { format: this.format(colored), paragraphs: false }), cli.replace(/\$0/g, this.binaryName)])
: undefined;
data.push({ path, usage, category, description, details, examples });
}
return data;
}
usage(command = null, { colored, detailed = false, prefix = `$ ` } = {}) {
// @ts-ignore
const commandClass = command !== null && typeof command.getMeta === `undefined`
? command.constructor
: command;
let result = ``;
if (!commandClass) {
const commandsByCategories = new Map();
for (const [commandClass, number] of this.registrations.entries()) {
if (typeof commandClass.usage === `undefined`)
continue;
const path = this.getUsageByIndex(number, { detailed: false });
const usage = this.getUsageByIndex(number, { detailed: true });
const category = typeof commandClass.usage.category !== `undefined`
? formatMarkdownish(commandClass.usage.category, { format: this.format(colored), paragraphs: false })
: undefined;
const description = typeof commandClass.usage.description !== `undefined`
? formatMarkdownish(commandClass.usage.description, { format: this.format(colored), paragraphs: false })
: undefined;
const details = typeof commandClass.usage.details !== `undefined`
? formatMarkdownish(commandClass.usage.details, { format: this.format(colored), paragraphs: true })
: undefined;
const examples = typeof commandClass.usage.examples !== `undefined`
? commandClass.usage.examples.map(([label, cli]) => [formatMarkdownish(label, { format: this.format(colored), paragraphs: false }), cli.replace(/\$0/g, this.binaryName)])
: undefined;
data.push({ path, usage, category, description, details, examples });
: null;
let categoryCommands = commandsByCategories.get(category);
if (typeof categoryCommands === `undefined`)
commandsByCategories.set(category, categoryCommands = []);
const usage = this.getUsageByIndex(number);
categoryCommands.push({ commandClass, usage });
}
return data;
}
usage(command = null, { colored, detailed = false, prefix = `$ ` } = {}) {
// @ts-ignore
const commandClass = command !== null && typeof command.getMeta === `undefined`
? command.constructor
: command;
let result = ``;
if (!commandClass) {
const commandsByCategories = new Map();
for (const [commandClass, number] of this.registrations.entries()) {
if (typeof commandClass.usage === `undefined`)
continue;
const category = typeof commandClass.usage.category !== `undefined`
? formatMarkdownish(commandClass.usage.category, { format: this.format(colored), paragraphs: false })
: null;
let categoryCommands = commandsByCategories.get(category);
if (typeof categoryCommands === `undefined`)
commandsByCategories.set(category, categoryCommands = []);
const usage = this.getUsageByIndex(number);
categoryCommands.push({ commandClass, usage });
}
const categoryNames = Array.from(commandsByCategories.keys()).sort((a, b) => {
if (a === null)
return -1;
if (b === null)
return +1;
return a.localeCompare(b, `en`, { usage: `sort`, caseFirst: `upper` });
const categoryNames = Array.from(commandsByCategories.keys()).sort((a, b) => {
if (a === null)
return -1;
if (b === null)
return +1;
return a.localeCompare(b, `en`, { usage: `sort`, caseFirst: `upper` });
});
const hasLabel = typeof this.binaryLabel !== `undefined`;
const hasVersion = typeof this.binaryVersion !== `undefined`;
if (hasLabel || hasVersion) {
if (hasLabel && hasVersion)
result += `${this.format(colored).bold(`${this.binaryLabel} - ${this.binaryVersion}`)}\n\n`;
else if (hasLabel)
result += `${this.format(colored).bold(`${this.binaryLabel}`)}\n`;
else
result += `${this.format(colored).bold(`${this.binaryVersion}`)}\n`;
result += ` ${this.format(colored).bold(prefix)}${this.binaryName} <command>\n`;
}
else {
result += `${this.format(colored).bold(prefix)}${this.binaryName} <command>\n`;
}
for (let categoryName of categoryNames) {
const commands = commandsByCategories.get(categoryName).slice().sort((a, b) => {
return a.usage.localeCompare(b.usage, `en`, { usage: `sort`, caseFirst: `upper` });
});
const hasLabel = typeof this.binaryLabel !== `undefined`;
const hasVersion = typeof this.binaryVersion !== `undefined`;
if (hasLabel || hasVersion) {
if (hasLabel && hasVersion)
result += `${this.format(colored).bold(`${this.binaryLabel} - ${this.binaryVersion}`)}\n\n`;
else if (hasLabel)
result += `${this.format(colored).bold(`${this.binaryLabel}`)}\n`;
else
result += `${this.format(colored).bold(`${this.binaryVersion}`)}\n`;
result += ` ${this.format(colored).bold(prefix)}${this.binaryName} <command>\n`;
}
else {
result += `${this.format(colored).bold(prefix)}${this.binaryName} <command>\n`;
}
for (let categoryName of categoryNames) {
const commands = commandsByCategories.get(categoryName).slice().sort((a, b) => {
return a.usage.localeCompare(b.usage, `en`, { usage: `sort`, caseFirst: `upper` });
});
const header = categoryName !== null
? categoryName.trim()
: `Where <command> is one of`;
const header = categoryName !== null
? categoryName.trim()
: `Where <command> is one of`;
result += `\n`;
result += `${this.format(colored).bold(`${header}:`)}\n`;
for (let { commandClass, usage } of commands) {
const doc = commandClass.usage.description || `undocumented`;
result += `\n`;
result += `${this.format(colored).bold(`${header}:`)}\n`;
for (let { commandClass, usage } of commands) {
const doc = commandClass.usage.description || `undocumented`;
result += `\n`;
result += ` ${this.format(colored).bold(usage)}\n`;
result += ` ${formatMarkdownish(doc, { format: this.format(colored), paragraphs: false })}`;
}
result += ` ${this.format(colored).bold(usage)}\n`;
result += ` ${formatMarkdownish(doc, { format: this.format(colored), paragraphs: false })}`;
}
result += `\n`;
result += formatMarkdownish(`You can also print more details about any of these commands by calling them after adding the \`-h,--help\` flag right after the command name.`, { format: this.format(colored), paragraphs: true });
}
result += `\n`;
result += formatMarkdownish(`You can also print more details about any of these commands by calling them after adding the \`-h,--help\` flag right after the command name.`, { format: this.format(colored), paragraphs: true });
}
else {
if (!detailed) {
result += `${this.format(colored).bold(prefix)}${this.getUsageByRegistration(commandClass)}\n`;
}
else {
if (!detailed) {
result += `${this.format(colored).bold(prefix)}${this.getUsageByRegistration(commandClass)}\n`;
const { description = ``, details = ``, examples = [], } = commandClass.usage || {};
if (description !== ``) {
result += formatMarkdownish(description, { format: this.format(colored), paragraphs: false }).replace(/^./, $0 => $0.toUpperCase());
result += `\n`;
}
else {
const { description = ``, details = ``, examples = [], } = commandClass.usage || {};
if (description !== ``) {
result += formatMarkdownish(description, { format: this.format(colored), paragraphs: false }).replace(/^./, $0 => $0.toUpperCase());
if (details !== `` || examples.length > 0) {
result += `${this.format(colored).bold(`Usage:`)}\n`;
result += `\n`;
}
result += `${this.format(colored).bold(prefix)}${this.getUsageByRegistration(commandClass)}\n`;
if (details !== ``) {
result += `\n`;
result += `${this.format(colored).bold(`Details:`)}\n`;
result += `\n`;
result += formatMarkdownish(details, { format: this.format(colored), paragraphs: true });
}
if (examples.length > 0) {
result += `\n`;
result += `${this.format(colored).bold(`Examples:`)}\n`;
for (let [description, example] of examples) {
result += `\n`;
result += formatMarkdownish(description, { format: this.format(colored), paragraphs: false });
result += example
.replace(/^/m, ` ${this.format(colored).bold(prefix)}`)
.replace(/\$0/g, this.binaryName)
+ `\n`;
}
if (details !== `` || examples.length > 0) {
result += `${this.format(colored).bold(`Usage:`)}\n`;
result += `\n`;
}
result += `${this.format(colored).bold(prefix)}${this.getUsageByRegistration(commandClass)}\n`;
if (details !== ``) {
result += `\n`;
result += `${this.format(colored).bold(`Details:`)}\n`;
result += `\n`;
result += formatMarkdownish(details, { format: this.format(colored), paragraphs: true });
}
if (examples.length > 0) {
result += `\n`;
result += `${this.format(colored).bold(`Examples:`)}\n`;
for (let [description, example] of examples) {
result += `\n`;
result += formatMarkdownish(description, { format: this.format(colored), paragraphs: false });
result += example
.replace(/^/m, ` ${this.format(colored).bold(prefix)}`)
.replace(/\$0/g, this.binaryName)
+ `\n`;
}
}
}
}
return result;
}
error(error, { colored, command = null } = {}) {
if (!(error instanceof Error))
error = new Error(`Execution failed with a non-error rejection (rejected value: ${JSON.stringify(error)})`);
let result = ``;
let name = error.name.replace(/([a-z])([A-Z])/g, `$1 $2`);
if (name === `Error`)
name = `Internal Error`;
result += `${this.format(colored).error(name)}: ${error.message}\n`;
// @ts-ignore
const meta = error.clipanion;
if (typeof meta !== `undefined`) {
if (meta.type === `usage`) {
result += `\n`;
result += this.usage(command);
}
return result;
}
error(error, { colored, command = null } = {}) {
if (!(error instanceof Error))
error = new Error(`Execution failed with a non-error rejection (rejected value: ${JSON.stringify(error)})`);
let result = ``;
let name = error.name.replace(/([a-z])([A-Z])/g, `$1 $2`);
if (name === `Error`)
name = `Internal Error`;
result += `${this.format(colored).error(name)}: ${error.message}\n`;
// @ts-ignore
const meta = error.clipanion;
if (typeof meta !== `undefined`) {
if (meta.type === `usage`) {
result += `\n`;
result += this.usage(command);
}
else {
if (error.stack) {
result += `${error.stack.replace(/^.*\n/, ``)}\n`;
}
}
else {
if (error.stack) {
result += `${error.stack.replace(/^.*\n/, ``)}\n`;
}
return result;
}
getUsageByRegistration(klass, opts) {
const index = this.registrations.get(klass);
if (typeof index === `undefined`)
throw new Error(`Assertion failed: Unregistered command`);
return this.getUsageByIndex(index, opts);
}
getUsageByIndex(n, opts) {
return this.builder.getBuilderByIndex(n).usage(opts);
}
format(colored = this.enableColors) {
return colored ? richFormat : textFormat;
}
return result;
}
/**
* The default context of the CLI.
*
* Contains the stdio of the current `process`.
*/
Cli.defaultContext = {
stdin: process.stdin,
stdout: process.stdout,
stderr: process.stderr,
};
return Cli;
})();
getUsageByRegistration(klass, opts) {
const index = this.registrations.get(klass);
if (typeof index === `undefined`)
throw new Error(`Assertion failed: Unregistered command`);
return this.getUsageByIndex(index, opts);
}
getUsageByIndex(n, opts) {
return this.builder.getBuilderByIndex(n).usage(opts);
}
format(colored = this.enableColors) {
return colored ? richFormat : textFormat;
}
}
/**
* The default context of the CLI.
*
* Contains the stdio of the current `process`.
*/
Cli.defaultContext = {
stdin: process.stdin,
stdout: process.stdout,
stderr: process.stderr,
};

@@ -1425,0 +1413,0 @@ Command.Entries.Help = HelpCommand;

{
"name": "clipanion",
"version": "2.4.1",
"version": "2.4.2",
"main": "lib/index",
"license": "MIT",
"repository": {
"url": "https://github.com/arcanis/clipanion",
"type": "git"
},
"devDependencies": {

@@ -10,14 +14,14 @@ "@types/chai": "^4.2.11",

"@types/mocha": "^7.0.2",
"@types/node": "^14.0.1",
"@types/yup": "^0.28.3",
"@wessberg/rollup-plugin-ts": "^1.2.24",
"@types/node": "^14.0.13",
"@types/yup": "^0.29.3",
"@wessberg/rollup-plugin-ts": "^1.2.25",
"chai": "^4.2.0",
"chai-as-promised": "^7.1.1",
"get-stream": "^5.1.0",
"mocha": "^7.1.2",
"rollup": "^2.12.0",
"ts-node": "^8.10.1",
"mocha": "^8.0.1",
"rollup": "^2.16.1",
"ts-node": "^8.10.2",
"tslib": "^2.0.0",
"typescript": "^3.9.2",
"yup": "^0.28.5"
"typescript": "^3.9.5",
"yup": "^0.29.1"
},

@@ -24,0 +28,0 @@ "scripts": {

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc