Repository URL to install this package:
|
Version:
0.6.0 ▾
|
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateCompletion = exports.getShellPaths = exports.detectShell = exports.Command = exports.Group = exports.createParser = void 0;
const argv_1 = require("./argv");
const parse_1 = require("./parse");
const path_1 = require("./path");
const print_1 = require("./print");
const shell_1 = require("./shell");
Object.defineProperty(exports, "detectShell", { enumerable: true, get: function () { return shell_1.detectShell; } });
Object.defineProperty(exports, "generateCompletion", { enumerable: true, get: function () { return shell_1.generateCompletion; } });
Object.defineProperty(exports, "getShellPaths", { enumerable: true, get: function () { return shell_1.getShellPaths; } });
const suggest_1 = require("./suggest");
const type_1 = require("./type");
Object.defineProperty(exports, "Command", { enumerable: true, get: function () { return type_1.Command; } });
Object.defineProperty(exports, "Group", { enumerable: true, get: function () { return type_1.Group; } });
function findOptionTargets(context, option) {
if (option.global) {
return context.sibling ? [context.options, context.sibling.options] : [context.options];
}
else {
const targets = [];
if (argv_1.findLongOption(context.command.options, option.key)) {
targets.push(context.options);
}
if (context.sibling && argv_1.findLongOption(context.sibling.command.options, option.key)) {
targets.push(context.sibling.options);
}
return targets;
}
}
function findArgumentTarget(context, commandArguments) {
if (context.sibling && context.argumentIndex < context.sibling.command.arguments.length) {
return context.sibling.arguments;
}
else if (context.argumentIndex < commandArguments.length) {
return context.arguments;
}
}
function createParser(options) {
const printer = (options && options.printer) || print_1.createDefaultPrinter();
const application = (options && options.application) || print_1.createDefaultApplication();
const pathResolver = (options && options.pathResolver) || path_1.completePath;
const exitCodeForParsingErrors = (options && options.exitCodeForParsingErrors) || 2;
const groups = [];
const commands = [];
const globalOptions = [];
const handleError = (context, reason, silent = false) => {
if (!context.group && !context.command) {
printer.print(print_1.getHeadlineMessage(application));
printer.print('');
print_1.printUsage(printer, application);
printer.print('');
print_1.printGroups(printer, application, groups);
print_1.printCommands(printer, application, commands);
print_1.maybePrintOptionFamily(printer, 'Global Options', globalOptions);
}
else if (!context.command && context.group) {
print_1.printUsage(printer, application, context.group);
printer.print('');
print_1.printCommands(printer, application, context.group.commands);
print_1.maybePrintOptionFamily(printer, 'Global Options', globalOptions);
}
else if (context.command) {
const siblingOptions = context.sibling ? context.sibling.command.options : [];
const options = [...globalOptions, ...context.command.options, ...siblingOptions];
const siblingArguments = context.sibling ? context.sibling.command.arguments : [];
const commandArguments = [...siblingArguments, ...context.command.arguments];
print_1.printCommandUsage(printer, application, context.command, options, commandArguments);
}
if (!context.options.help && !silent) {
printer.printHeading('Command failed with reason:');
printer.print('');
printer.printError(reason);
}
if (!context.options.help && process) {
process.exitCode = exitCodeForParsingErrors;
}
return reason;
};
// eslint-disable-next-line complexity
function populate(argv, context, profile) {
const sibling = context.command.sibling
? argv_1.findCommandByFullPath(groups, commands, context.command.sibling)
: undefined;
if (context.command.sibling && !sibling) {
return handleError(context, 'Expected sibling command not found!');
}
if (sibling) {
context.sibling = {
command: sibling,
arguments: {},
options: {},
};
}
const siblingOptions = sibling ? sibling.options : [];
const options = [...globalOptions, ...context.command.options, ...siblingOptions];
const siblingArguments = sibling ? sibling.arguments : [];
const commandArguments = [...siblingArguments, ...context.command.arguments];
if (context.options.help) {
print_1.printCommandUsage(printer, application, context.command, options, commandArguments);
return { exitReason: 'help' };
}
const skipAmount = context.command.depth + 1;
for (let i = skipAmount; i < argv.length; i++) {
const current = argv[i];
const next = argv[i + 1];
if (argv_1.isOption(current)) {
const option = argv_1.findOption(options, current);
if (!option) {
return handleError(context, 'Unexpected option: ' + current);
}
const parseResult = parse_1.parseValue(option, next);
if (parseResult instanceof Error) {
return handleError(context, parseResult.message);
}
const targets = findOptionTargets(context, option);
for (const target of targets) {
if (option.array) {
if (!target[option.key]) {
target[option.key] = [];
context.sourcemap[option.key] = 'explicit';
}
;
target[option.key].push(parseResult.value);
}
else {
if (target[option.key] !== undefined) {
return handleError(context, 'Option passed more than once: ' + option.key);
}
target[option.key] = parseResult.value;
context.sourcemap[option.key] = 'explicit';
}
}
i += parseResult.skip;
}
else {
const target = findArgumentTarget(context, commandArguments);
if (!target) {
return handleError(context, 'Unexpected argument: ' + current);
}
const argument = commandArguments[context.argumentIndex++];
const parseResult = parse_1.parseValue(argument, current);
if (parseResult instanceof Error) {
return handleError(context, parseResult.message);
}
target[argument.key] = parseResult.value;
context.sourcemap[argument.key] = 'explicit';
}
}
for (const option of options) {
if (!option.envKey) {
continue;
}
if (process.env[option.envKey] === undefined) {
continue;
}
const parseResult = parse_1.parseValue(option, process.env[option.envKey]);
if (parseResult instanceof Error) {
return handleError(context, parseResult.message);
}
const targets = findOptionTargets(context, option);
for (const target of targets) {
if (target[option.key] !== undefined) {
continue;
}
target[option.key] = parseResult.value;
context.sourcemap[option.key] = 'env';
}
}
context.argumentIndex = 0;
if (commandArguments.length !== 1 ||
!commandArguments[0].conflicts ||
context.sourcemap[commandArguments[0].conflicts] !== 'explicit') {
for (const commandArgument of commandArguments) {
const target = findArgumentTarget(context, commandArguments);
context.argumentIndex++;
if (target[commandArgument.key] === undefined) {
if (commandArgument.default !== undefined) {
target[commandArgument.key] = commandArgument.default;
context.sourcemap[commandArgument.key] = 'default';
}
else if (commandArgument.required && !commandArgument.noErrors) {
const silent = argv.join(' ') === context.command.fullPath;
return handleError(context, `Required argument [${commandArgument.key}] is not provided`, silent);
}
}
}
}
if (profile) {
profile = Object.assign({}, profile);
if (!profile.globalOptions) {
profile.globalOptions = {};
}
if (!profile[context.command.fullPath]) {
profile[context.command.fullPath] = {};
}
const activeProfile = Object.assign(Object.assign({}, profile[context.command.fullPath]), profile.globalOptions);
for (const key in activeProfile) {
if (key === 'globalOptions') {
continue;
}
if (context.sourcemap[key] === 'explicit') {
continue;
}
const option = options.find(x => x.key === key);
if (!option) {
continue;
}
if (option.conflicts && ['explicit', 'profile'].includes(context.sourcemap[option.conflicts])) {
continue;
}
const parseResult = parse_1.parseValue(option, String(activeProfile[key]));
if (parseResult instanceof Error) {
context.profileErrors.push(parseResult.message);
continue;
}
const targets = findOptionTargets(context, option);
for (const target of targets) {
target[option.key] = parseResult.value;
}
context.sourcemap[key] = 'profile';
}
}
for (const option of options) {
const targets = findOptionTargets(context, option);
for (const target of targets) {
if (option.array && !target[option.key]) {
target[option.key] = [];
}
}
if (option.default !== undefined && (!option.conflicts || context.options[option.conflicts] === undefined)) {
for (const target of targets) {
if (target[option.key] !== undefined) {
continue;
}
target[option.key] = option.default;
context.sourcemap[option.key] = 'default';
}
}
if (option.conflicts &&
context.options[option.key] &&
(context.options[option.conflicts] || context.arguments[option.conflicts])) {
return handleError(context, `[${option.key}] and [${option.conflicts}] are incompatible, please only specify one`);
}
if (option.required && !option.noErrors) {
for (const target of targets) {
const requiredWhen = typeof option.required === 'object' && 'when' in option.required ? option.required.when : undefined;
const requiredUnless = typeof option.required === 'object' && 'unless' in option.required ? option.required.unless : undefined;
if ((target[option.key] === undefined ||
(context.sourcemap[option.key] === 'default' &&
requiredWhen &&
target[requiredWhen] &&
context.sourcemap[requiredWhen] !== 'default')) &&
(!option.conflicts || !target[option.conflicts]) &&
(!requiredWhen || target[requiredWhen]) &&
(!requiredUnless || !target[requiredUnless])) {
return handleError(context, 'Required option not provided: --' + option.key);
}
}
}
}
return context;
}
return {
addGlobalOption: (option) => {
option.global = true;
globalOptions.push(option);
},
addGroup: (group) => {
groups.push(group);
},
addCommand: (command) => {
commands.push(command);
},
suggest: (line, offset = 0, trailing = '') => __awaiter(this, void 0, void 0, function* () {
return suggest_1.suggest(line, offset, [...groups, ...commands], globalOptions, pathResolver, trailing);
}),
parse: (argv, profile = null) => __awaiter(this, void 0, void 0, function* () {
const context = {
options: {},
arguments: {},
sourcemap: {},
argumentIndex: 0,
profileErrors: [],
};
const findResult = argv_1.findGroupAndCommand(argv, groups, commands);
context.group = findResult.group;
context.command = findResult.command;
for (const option of globalOptions) {
if (argv_1.isOptionPassed(argv, option)) {
if (option.handler) {
yield option.handler();
return { exitReason: option.key };
}
if (option.key === 'help') {
context.options.help = true;
}
}
}
if (!context.group && !context.command) {
if (argv.join(' ') === '') {
return handleError(context, 'No group or command specified', true);
}
else {
return handleError(context, 'Not a valid group or command: ' + argv[0]);
}
}
if (context.group && !context.command) {
if (argv.join(' ') === context.group.fullPath) {
return handleError(context, `You need to specify a command in group [${context.group.key}]`, true);
}
else {
const depth = context.group.fullPath.split(' ').length;
return handleError(context, 'Not a valid command in group [' + context.group.key + ']: ' + argv[depth]);
}
}
if (!context.command) {
return handleError(context, 'No command found!');
}
return populate(argv, context, profile);
}),
};
}
exports.createParser = createParser;