1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- 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
|