travel/admin/node_modules/microcli/index.js

78 lines
2.2 KiB
JavaScript

const path = require('path')
const microargs = require('microargs')
const { get, difference, isEmpty, padEnd, forEach, capitalize, omit, isString } = require('lodash')
class CLIError extends Error { }
function optionToString (optionName) {
return optionName.length === 1 ? `-${optionName}` : `--${optionName}`
}
function optionsToString (optionsKeys) {
return optionsKeys.map(optionToString).join(' ')
}
function printHelp (scriptName, annotations, logger) {
if (isEmpty(annotations)) {
logger.log('Documentation not found')
return null
}
const { description, params, options } = annotations
const extra = omit(annotations, ['description', 'params', 'options'])
const usageOptions = isEmpty(options) ? '' : '[options]'
const usageParams = isEmpty(params) ? '' : `[${params.join(' ')}]`
logger.log(`Usage: ${path.basename(scriptName)} ${usageOptions} ${usageParams}\n`)
if (description) {
logger.log(`${description}\n`)
}
if (!isEmpty(options)) {
logger.log('Options:\n')
forEach(options, (value, key) => {
logger.log(` ${padEnd(optionToString(key), 12)}${value}`)
})
}
forEach(extra, (value, key) => {
logger.log(`\n${capitalize(key)}:\n`)
logger.log(`${value}\n`)
})
}
module.exports = (argv, annotations = {}, help, logger = console) => {
help = help || printHelp
return (callback) => {
const { params, options } = microargs(argv.slice(2))
const scriptName = path.basename(argv[1])
if (isString(annotations)) {
annotations = {
description: annotations
}
}
if (options.help) {
return help(scriptName, annotations, logger)
}
const annotatedOptionsKeys = (get(annotations, 'options') && Object.keys(annotations.options)) || []
const optionsKeys = Object.keys(options)
const illegalOptionsKeys = difference(optionsKeys, annotatedOptionsKeys)
if (annotatedOptionsKeys.length && illegalOptionsKeys.length) {
const msg = `Illegal option: ${optionsToString(illegalOptionsKeys)}\n` +
`Available options: ${optionsToString(annotatedOptionsKeys)}\n` +
`Type "${scriptName} --help" for more information`
throw new CLIError(msg)
}
return callback(options, ...params)
}
}
module.exports.CLIError = CLIError