You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							77 lines
						
					
					
						
							2.2 KiB
						
					
					
				
			
		
		
	
	
							77 lines
						
					
					
						
							2.2 KiB
						
					
					
				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
 | 
						|
 |