Socket
Socket
Sign inDemoInstall

clipanion

Package Overview
Dependencies
1
Maintainers
1
Versions
83
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.0.0-rc.6 to 2.0.0-rc.8

lib/pretty.d.ts

20

lib/advanced/Cli.d.ts
/// <reference types="node" />
import { Readable, Writable } from 'stream';
import * as core from '../core';
import { Command } from './Command';
import { CommandClass, Command } from './Command';
export interface DefaultContext {

@@ -10,6 +9,2 @@ stdin: Readable;

}
export interface CommandFactory<Context extends DefaultContext> {
new (): Command<Context>;
compile(): core.Command<(cli: MiniCli<Context>, context: Context) => Command<Context>>;
}
export interface MiniCli<Context extends DefaultContext> {

@@ -20,8 +15,11 @@ process(argv: string[]): Command<Context>;

export declare class Cli<Context extends DefaultContext = DefaultContext> {
private readonly core;
readonly name?: string;
constructor({ name }?: {
name?: string;
private readonly coreCli;
private readonly binaryName;
private readonly registrations;
constructor({ binaryName }?: {
binaryName?: string;
});
register(command: CommandFactory<Context>): this;
register(advancedCommand: CommandClass<Context>): void;
private registerGeneralHelp;
private registerDefinitions;
start(): import("../core/Machine").Machine<(cli: MiniCli<Context>, context: Context) => Command<Context>>;

@@ -28,0 +26,0 @@ process(argv: string[]): (cli: MiniCli<Context>, context: Context) => Command<Context>;

"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -15,17 +21,130 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

const core = __importStar(require("../core"));
const pretty_1 = require("../pretty");
const Command_1 = require("./Command");
class Cli {
constructor({ name } = {}) {
this.core = new core.Cli();
this.name = name;
constructor({ binaryName = `...` } = {}) {
this.coreCli = new core.Cli();
this.registrations = [];
this.binaryName = binaryName;
this.registerDefinitions();
this.registerGeneralHelp();
}
register(command) {
this.core.register(command.compile());
return this;
register(advancedCommand) {
const coreCommand = advancedCommand.compile();
this.registrations.push({ advancedCommand, coreCommand });
this.coreCli.register(coreCommand);
}
registerGeneralHelp() {
const self = this;
class GeneralHelpListing extends Command_1.Command {
async execute() {
const commandsByCategories = new Map();
let maxPathLength = 0;
for (const { advancedCommand, coreCommand } of self.registrations) {
if (typeof advancedCommand.usage === `undefined`)
continue;
const category = typeof advancedCommand.usage.category !== `undefined`
? pretty_1.prettyMarkdownish(advancedCommand.usage.category, false)
: undefined;
let categoryCommands = commandsByCategories.get(category);
if (typeof categoryCommands === `undefined`)
commandsByCategories.set(category, categoryCommands = []);
const path = coreCommand.definition.path.join(` `);
categoryCommands.push({ command: advancedCommand, path });
const pathLength = path.length;
if (pathLength > maxPathLength) {
maxPathLength = pathLength;
}
}
const categoryNames = Array.from(commandsByCategories.keys()).sort((a, b) => {
if (a === undefined)
return -1;
if (b === undefined)
return +1;
return a.localeCompare(b, `en`, { usage: `sort`, caseFirst: `upper` });
});
this.context.stdout.write(self.usage(null));
for (let categoryName of categoryNames) {
const commands = commandsByCategories.get(categoryName).slice().sort((a, b) => {
return a.path.localeCompare(b.path, `en`, { usage: `sort`, caseFirst: `upper` });
});
const header = typeof categoryName !== `undefined`
? categoryName.trim()
: `Where <command> is one of`;
this.context.stdout.write(`\n`);
this.context.stdout.write(`${chalk_1.default.bold(`${header}:`)}\n`);
this.context.stdout.write(`\n`);
const pad = (str) => `${str}${` `.repeat(maxPathLength - str.length)}`;
for (let { command, path } of commands) {
const doc = command.usage.description || `undocumented`;
this.context.stdout.write(` ${chalk_1.default.bold(pad(path))} ${pretty_1.prettyMarkdownish(doc, false)}`);
}
}
}
}
__decorate([
Command_1.Command.HideFromErrors()
], GeneralHelpListing.prototype, "execute", null);
const coreCommand = GeneralHelpListing.compile();
// We replace the link function so that we can inject a special logic
// into the state machine (instead of the default one which would check
// the path, options, etc).
coreCommand.link = function ({ proxyStart }) {
if (typeof proxyStart === `undefined` || proxyStart >= 1) {
const generalHelpNode = this.createNode({ weight: 0, label: `activate the general help` });
this.registerTransition(core.NODE_INITIAL, `-h`, generalHelpNode);
this.registerTransition(core.NODE_INITIAL, `--help`, generalHelpNode);
this.markTerminal(generalHelpNode);
}
};
this.coreCli.register(coreCommand);
}
registerDefinitions() {
const self = this;
class DefinitionsCommand extends Command_1.Command {
async execute() {
const data = [];
for (const { advancedCommand, coreCommand } of self.registrations) {
if (typeof advancedCommand.usage === `undefined`)
continue;
const path = [self.binaryName, ...coreCommand.definition.path];
const usage = pretty_1.prettyCommand(coreCommand.definition, { binaryName: self.binaryName });
const category = typeof advancedCommand.usage.category !== `undefined`
? pretty_1.prettyMarkdownish(advancedCommand.usage.category, false)
: undefined;
const description = typeof advancedCommand.usage.description !== `undefined`
? pretty_1.prettyMarkdownish(advancedCommand.usage.description, false)
: undefined;
const details = typeof advancedCommand.usage.details !== `undefined`
? pretty_1.prettyMarkdownish(advancedCommand.usage.details, true)
: undefined;
const examples = typeof advancedCommand.usage.examples !== `undefined`
? advancedCommand.usage.examples.map(([label, cli]) => [pretty_1.prettyMarkdownish(label, false), pretty_1.prettyMarkdownish(cli, false)])
: undefined;
data.push({ path, usage, category, description, details, examples });
}
this.context.stdout.write(JSON.stringify(data, null, 2) + `\n`);
}
}
__decorate([
Command_1.Command.HideFromErrors()
], DefinitionsCommand.prototype, "execute", null);
const coreCommand = DefinitionsCommand.compile();
// We replace the link function so that we can inject a special logic
// into the state machine (instead of the default one which would check
// the path, options, etc).
coreCommand.link = function ({ proxyStart }) {
if (typeof proxyStart === `undefined` || proxyStart >= 1) {
const definitionNode = this.createNode({ weight: 1, label: `activate the definitions` });
this.registerTransition(core.NODE_INITIAL, `--clipanion=definitions`, definitionNode);
this.markTerminal(definitionNode);
}
};
this.coreCli.register(coreCommand);
}
start() {
return this.core.start();
return this.coreCli.start();
}
process(argv) {
return this.core.process(argv);
return this.coreCli.process(argv);
}

@@ -43,7 +162,7 @@ async run(argv, context) {

try {
command = this.core.process(argv)(cli, context);
command = this.coreCli.process(argv)(cli, context);
}
catch (error) {
if (typeof error.setBinaryName !== `undefined`)
error.setBinaryName(this.name);
error.setBinaryName(this.binaryName);
context.stderr.write(this.error(error));

@@ -73,14 +192,37 @@ return 1;

let result = ``;
if (command) {
if (this.name)
result += `$ ${this.name} ${core.prettyCommand(Command_1.Command.getMeta(command).definition)}\n`;
else
result += `${core.prettyCommand(Command_1.Command.getMeta(command).definition)}\n`;
if (detailed) {
const usage = typeof command.usage !== `undefined`
? command.usage()
: ``;
if (usage) {
result += `\n${usage}`;
if (!command) {
result += `${chalk_1.default.bold(`$`)} ${this.binaryName} <command>\n`;
}
else {
const { definition } = command.constructor.getMeta();
if (!detailed) {
result += `${chalk_1.default.bold(`$`)} ${pretty_1.prettyCommand(definition, { binaryName: this.binaryName })}\n`;
}
else {
const { description = ``, details = ``, examples = [], } = command.constructor.usage || {};
if (description !== ``) {
result += pretty_1.prettyMarkdownish(description, false).replace(/^./, $0 => $0.toUpperCase());
result += `\n`;
}
if (details !== `` || examples.length > 0) {
result += `${chalk_1.default.bold(`Usage:`)}\n`;
result += `\n`;
}
result += `${chalk_1.default.bold(`$`)} ${pretty_1.prettyCommand(definition, { binaryName: this.binaryName })}\n`;
if (details !== ``) {
result += `\n`;
result += `${chalk_1.default.bold(`Details:`)}\n`;
result += `\n`;
result += pretty_1.prettyMarkdownish(details, true);
}
if (examples.length > 0) {
result += `\n`;
result += `${chalk_1.default.bold(`Examples:`)}\n`;
for (let [description, example] of examples) {
result += `\n`;
result += description;
result += `\n`;
result += example.replace(/^/m, ` `);
}
}
}

@@ -87,0 +229,0 @@ }

import * as core from '../core';
import { DefaultContext, MiniCli } from './Cli';
export declare type Help = {
export declare type Usage = Partial<{
category: string | undefined;
description: string;
details: string;
examples: {
description: string;
command: string;
}[];
};
examples: [string, string][];
}>;
export declare type Meta = {

@@ -16,2 +13,7 @@ definition: core.Definition;

};
export interface CommandClass<Context extends DefaultContext = DefaultContext> {
new (): Command<Context>;
compile(): core.Command<(cli: MiniCli<Context>, context: Context) => Command<Context>>;
usage?: Usage;
}
export declare abstract class Command<Context extends DefaultContext = DefaultContext> {

@@ -21,2 +23,3 @@ static meta: Meta | undefined;

static Validate(schema: any): (klass: any) => void;
static HideFromErrors(): <Context extends DefaultContext>(prototype: Command<Context>, propertyName: "execute") => void;
static Array(descriptor: string): <Context extends DefaultContext>(prototype: Command<Context>, propertyName: string) => void;

@@ -35,3 +38,8 @@ static Rest(): PropertyDecorator;

static Path(...segments: string[]): <Context extends DefaultContext>(prototype: Command<Context>, propertyName: "execute") => void;
static Usage({ category, description, details }?: Partial<Help>): () => string;
static Usage(usage: Usage): Partial<{
category: string | undefined;
description: string;
details: string;
examples: [string, string][];
}>;
static compile<Context extends DefaultContext>(): core.Command<(cli: MiniCli<Context>, context: Context) => Command<Context>>;

@@ -46,3 +54,3 @@ cli: MiniCli<Context>;

*/
usage: (() => string) | undefined;
static usage?: Usage;
/**

@@ -49,0 +57,0 @@ * Executed by Cli#run and Cli#runExit.

@@ -32,2 +32,5 @@ "use strict";

},
flags: {
hideFromErrors: false,
},
},

@@ -62,2 +65,8 @@ transformers: [

}
static HideFromErrors() {
return (prototype, propertyName) => {
const { definition } = prototype.constructor.getMeta();
definition.flags.hideFromErrors = true;
};
}
static Array(descriptor) {

@@ -159,17 +168,4 @@ const optionNames = new Set(descriptor.split(/,/g));

}
static Usage({ category, description, details } = {}) {
return () => {
let result = ``;
if (typeof details !== `undefined`) {
if (result !== ``)
result += `\n`;
result += core.prettyMarkdownish(details, true);
}
else if (typeof description !== `undefined`) {
if (result !== ``)
result += `\n`;
result += core.prettyMarkdownish(description, false);
}
return result;
};
static Usage(usage) {
return usage;
}

@@ -176,0 +172,0 @@ static compile() {

export { UsageError } from '../core';
export { Cli, CommandFactory, DefaultContext } from './Cli';
export { Command } from './Command';
export { Cli, DefaultContext } from './Cli';
export { CommandClass, Command } from './Command';

@@ -34,2 +34,5 @@ import { RecursivePartial } from '../mpl';

};
flags: {
hideFromErrors: boolean;
};
};

@@ -45,11 +48,15 @@ export declare class Command<T> {

}): void;
link({ proxyStart }: {
proxyStart: number | undefined;
}): void;
createNode({ weight, label, suggested }: {
weight: number;
weight?: number;
label: string;
suggested?: boolean;
}): number;
markTerminal(node: number | null): void;
registerTransition(node: number | null, segment: string | null, target: number, builder?: keyof typeof builders): void;
registerDynamicTransition(node: number | null, condition: keyof typeof conditions, target: number, builder?: keyof typeof builders): void;
registerOptions(node: number | null): void;
cloneNode(node: number): number;
markTerminal(node: number): void;
registerTransition(node: number, segment: string | null, target: number, builder?: keyof typeof builders): void;
registerDynamicTransition(node: number, condition: keyof typeof conditions, target: number, builder?: keyof typeof builders): void;
registerOptions(from: number, to?: number): void;
}

@@ -19,2 +19,5 @@ "use strict";

},
flags: {
hideFromErrors: false,
},
};

@@ -31,2 +34,3 @@ class Command {

return;
this.compiled = true;
this.createNode({ weight: 0, label: `initial` });

@@ -38,3 +42,5 @@ this.createNode({ weight: 0, label: `success` });

this.registerTransition(exports.NODE_ERRORED, null, exports.NODE_ERRORED);
this.compiled = true;
this.link({ proxyStart });
}
link({ proxyStart }) {
const initialDD = this.createNode({ weight: 0, label: `initial (no opts)` });

@@ -76,2 +82,4 @@ this.registerTransition(0, `--`, initialDD);

}
this.markTerminal(lastMinNode);
this.markTerminal(lastMinNodeDD);
const allMaxNodes = [];

@@ -117,4 +125,9 @@ const allMaxNodesDD = [];

}
for (const node of allMaxNodes)
this.markTerminal(node);
for (const node of allMaxNodesDD)
this.markTerminal(node);
this.registerDynamicTransition(lastMaxNode, `isPositionalArgument`, exports.NODE_ERRORED, `generateExtraneousPositionalArgument`);
this.registerDynamicTransition(lastMaxNodeDD, `always`, exports.NODE_ERRORED, `generateExtraneousPositionalArgument`);
const lastPathAnyHelpNode = this.cloneNode(lastPathNode);
/* The following block exclusively adds support for -h and --help */ {

@@ -128,43 +141,41 @@ // We can't support -h,--help if a proxy starts immediately after the command

// Register the transition from the path to the help
for (const optName of exports.HELP_OPTIONS)
this.registerTransition(lastPathNode, optName, afterHelpNode, `generateBoolean`);
if (lastPathNode !== exports.NODE_INITIAL) {
for (const optName of exports.HELP_OPTIONS) {
this.registerTransition(lastPathNode, optName, lastPathNode, `generateBoolean`);
}
}
else {
const lastPathNonTerminalNode = this.cloneNode(lastPathNode);
this.nodes[lastPathNonTerminalNode].transitions.delete(null);
this.registerOptions(lastPathNonTerminalNode, lastPathAnyHelpNode);
for (const optName of exports.HELP_OPTIONS) {
this.registerTransition(lastPathNode, optName, lastPathNonTerminalNode, `generateBoolean`);
this.registerTransition(lastPathNonTerminalNode, optName, lastPathAnyHelpNode, `generateBoolean`);
this.registerTransition(lastPathAnyHelpNode, optName, lastPathAnyHelpNode, `generateBoolean`);
}
}
// Same thing for the mandatory positional arguments, but we give them some weight
for (let t = 0; t < this.definition.positionals.minimum; ++t) {
for (const minNode of allMinNodes) {
for (const optName of exports.HELP_OPTIONS) {
// Note that we don't add this transition to allMinNodesDD, since we don't want to find -h,--help if behind --
this.registerTransition(allMinNodes[t], optName, afterHelpNode, `generateBoolean`);
this.registerTransition(minNode, optName, afterHelpNode, `generateBoolean`);
}
}
// If there are no proxy we can just consume everything until -h,--help
if (typeof proxyStart === `undefined`) {
const searchHelpNode = this.createNode({ weight: 0, label: `looking for -h,--help`, suggested: false });
this.registerDynamicTransition(lastMinNode, `isUnsupportedOption`, searchHelpNode);
this.registerDynamicTransition(lastMaxNode, `isPositionalArgument`, searchHelpNode);
this.registerDynamicTransition(searchHelpNode, `isNotHelpNorSeparator`, searchHelpNode);
// If there are no proxy we can just consume as usual
// Otherwise we need to count what we eat so that we don't enter the Proxy Zone™
let lookAheadSize = typeof proxyStart !== `undefined`
? proxyStart - this.definition.path.length - this.definition.positionals.minimum
: Infinity;
for (const maxNode of allMinNodes) {
if (--lookAheadSize === 0)
break;
for (const optName of exports.HELP_OPTIONS) {
this.registerTransition(searchHelpNode, optName, afterHelpNode, `generateBoolean`);
// Note that we don't add this transition to allMinNodesDD, since we don't want to find -h,--help if behind --
this.registerTransition(maxNode, optName, afterHelpNode, `generateBoolean`);
}
// Otherwise we need to count what we eat so that we don't enter the Proxy Zone™
}
else {
const lookAheadSize = proxyStart - this.definition.path.length - this.definition.positionals.minimum - 1;
let lastHelpNode = lastPathNode;
for (let t = 0; t < lookAheadSize; ++t) {
const currentHelpNode = this.createNode({ weight: 0, label: `looking for help (${t + 1}/${proxyStart})`, suggested: false });
this.registerDynamicTransition(lastHelpNode, `isPositionalArgument`, currentHelpNode);
this.registerDynamicTransition(currentHelpNode, `isOptionLikeButNotHelp`, currentHelpNode);
for (const optName of exports.HELP_OPTIONS)
this.registerTransition(currentHelpNode, optName, afterHelpNode, `generateBoolean`);
lastHelpNode = currentHelpNode;
}
}
}
}
this.registerOptions(lastPathNode);
this.markTerminal(lastMinNode);
this.markTerminal(lastMinNodeDD);
for (const node of allMaxNodes)
this.markTerminal(node);
for (const node of allMaxNodesDD)
this.markTerminal(node);
this.registerOptions(lastPathNode, lastPathAnyHelpNode);
this.registerOptions(lastPathAnyHelpNode);
for (const node of allMinNodes)

@@ -176,6 +187,11 @@ this.registerOptions(node);

}
createNode({ weight, label, suggested = true }) {
createNode({ weight = 0, label, suggested = true }) {
this.nodes.push({ label, suggested, weight, transitions: new Map(), dynamics: [] });
return this.nodes.length - 1;
}
cloneNode(node) {
const source = this.nodes[node];
this.nodes.push(Object.assign({}, source, { transitions: new Map(source.transitions), dynamics: source.dynamics.slice() }));
return this.nodes.length - 1;
}
markTerminal(node) {

@@ -185,27 +201,21 @@ this.registerTransition(node, null, 1);

registerTransition(node, segment, target, builder) {
if (node !== null) {
this.nodes[node].transitions.set(segment, { target, builder });
}
this.nodes[node].transitions.set(segment, { target, builder });
}
registerDynamicTransition(node, condition, target, builder) {
if (node !== null) {
this.nodes[node].dynamics.push({ condition, target, builder });
}
this.nodes[node].dynamics.push({ condition, target, builder });
}
registerOptions(node) {
if (node === null)
return;
this.registerDynamicTransition(node, `isUnsupportedOption`, exports.NODE_ERRORED, `generateUnsupportedOption`);
registerOptions(from, to = from) {
this.registerDynamicTransition(from, `isUnsupportedOption`, exports.NODE_ERRORED, `generateUnsupportedOption`);
if (this.definition.options.simple.size > 0) {
this.registerDynamicTransition(node, `isOptionBatch`, node, `generateBooleansFromBatch`);
this.registerDynamicTransition(from, `isOptionBatch`, to, `generateBooleansFromBatch`);
for (const optName of this.definition.options.simple) {
this.registerTransition(node, optName, node, `generateBoolean`);
this.registerTransition(from, optName, to, `generateBoolean`);
}
}
if (this.definition.options.complex.size > 0) {
this.registerDynamicTransition(node, `isInlineOption`, node, `generateStringFromInline`);
this.registerDynamicTransition(from, `isInlineOption`, to, `generateStringFromInline`);
for (const optName of this.definition.options.complex) {
const argNode = this.createNode({ weight: 0, label: `consuming argument` });
this.registerDynamicTransition(argNode, `isPositionalArgument`, node, `generateStringValue`);
this.registerTransition(node, optName, argNode, `generateStringKey`);
this.registerDynamicTransition(argNode, `isPositionalArgument`, to, `generateStringValue`);
this.registerTransition(from, optName, argNode, `generateStringKey`);
}

@@ -212,0 +222,0 @@ }

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const pretty_1 = require("./pretty");
const pretty_1 = require("../pretty");
class UsageError extends Error {

@@ -5,0 +5,0 @@ constructor(message) {

export { Cli } from './Cli';
export { NODE_INITIAL, NODE_SUCCESS, NODE_ERRORED } from './Command';
export { Command, Definition } from './Command';
export { ErrorMeta, UsageError } from './errors';
export { Parsed } from './helpers';
export { prettyCommand, prettyMarkdownish } from './pretty';

@@ -6,7 +6,8 @@ "use strict";

var Command_1 = require("./Command");
exports.Command = Command_1.Command;
exports.NODE_INITIAL = Command_1.NODE_INITIAL;
exports.NODE_SUCCESS = Command_1.NODE_SUCCESS;
exports.NODE_ERRORED = Command_1.NODE_ERRORED;
var Command_2 = require("./Command");
exports.Command = Command_2.Command;
var errors_1 = require("./errors");
exports.UsageError = errors_1.UsageError;
var pretty_1 = require("./pretty");
exports.prettyCommand = pretty_1.prettyCommand;
exports.prettyMarkdownish = pretty_1.prettyMarkdownish;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const pretty_1 = require("../pretty");
const Command_1 = require("./Command");

@@ -8,3 +9,2 @@ const builders_1 = require("./builders");

const helpers_1 = require("./helpers");
const pretty_1 = require("./pretty");
class Machine {

@@ -42,5 +42,5 @@ constructor(commands) {

if (successes.length < 1)
throw new errors_1.UnknownSyntaxError(failures.map(({ command, reason }) => [command.definition, reason]));
throw new errors_1.UnknownSyntaxError(failures.filter(({ command }) => !command.definition.flags.hideFromErrors).map(({ command, reason }) => [command.definition, reason]));
if (successes.length > 1)
throw new errors_1.AmbiguousSyntaxError(successes.map(({ command }) => command.definition));
throw new errors_1.AmbiguousSyntaxError(successes.filter(({ command }) => !command.definition.flags.hideFromErrors).map(({ command }) => command.definition));
const [{ command, parsed }] = successes;

@@ -47,0 +47,0 @@ if (helpers_1.DEBUG)

{
"name": "clipanion",
"version": "2.0.0-rc.6",
"version": "2.0.0-rc.8",
"main": "lib/advanced",

@@ -5,0 +5,0 @@ "license": "MIT",

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc