UNPKG

make-cli

Version:

Super easy declarative CLI framework with a single configuration object and a single function call.

99 lines 2.87 kB
import defu from "@dword-design/defu"; import { Command as CommanderCommand, Option as CommanderOption } from "commander"; import { compact } from "lodash-es"; import pIsPromise from "p-is-promise"; const applyOptions = (program, options = []) => { for (const option of options) { const commanderOption = new CommanderOption(option.name, option.description); commanderOption.default(option.defaultValue); if (option.choices) { commanderOption.choices(option.choices); } program.addOption(commanderOption); } }; const getNormalizedOptions = options => { if (options === void 0) { return []; } if (Array.isArray(options)) { return options; } return Object.entries(options).map(([name, option]) => defu(option, { name })); }; const getNormalizedCommands = commands => { if (commands === void 0) { return []; } if (Array.isArray(commands)) { return commands.map(command => ({ ...command, handler: ignoreReturn(command.handler), options: getNormalizedOptions(command.options) })); } return Object.entries(commands).map(([name, command]) => ({ name, ...(typeof command === "function" ? { handler: ignoreReturn(command), options: [] } : { ...command, handler: ignoreReturn(command.handler), options: getNormalizedOptions(command.options) }) })); }; const ignoreReturn = func => (...args) => { const result = func(...args); if (pIsPromise(result)) { return Promise.resolve(); } }; export default (configInput = {}) => { const config = defu({ ...configInput, commands: getNormalizedCommands(configInput.commands), options: getNormalizedOptions(configInput.options), ...(configInput.action && { action: ignoreReturn(configInput.action) }) }, { allowUnknownOption: false }); const program = new CommanderCommand(); if (config.version) { program.version(config.version); } if (config.name) { program.name(config.name); } if (config.usage) { program.usage(config.usage); } if (config.arguments) { program.arguments(config.arguments); } if (config.allowUnknownOption) { program.allowUnknownOption(); } applyOptions(program, config.options); if (config.action) { program.action(config.action); } for (const command of config.commands) { const cmd = program.command(compact([command.name, command.arguments]).join(" ")); cmd.description(command.description); cmd.action(command.handler); applyOptions(cmd, command.options); } if (config.defaultCommandName && process.argv.length <= 2) { return config.commands.find(command => command.name === config.defaultCommandName).handler(); } if (config.commands.length > 0) { program.on("command:*", () => program.help()); } return program.parseAsync(process.argv); };