|  | 'use strict'; | 
|  |  | 
|  | const yargs = require('yargs/yargs'); | 
|  | const flatten = require('flat'); | 
|  | const castArray = require('lodash/castArray'); | 
|  | const some = require('lodash/some'); | 
|  | const isPlainObject = require('lodash/isPlainObject'); | 
|  | const camelCase = require('lodash/camelCase'); | 
|  | const kebabCase = require('lodash/kebabCase'); | 
|  | const omitBy = require('lodash/omitBy'); | 
|  |  | 
|  | function isAlias(key, alias) { | 
|  | return some(alias, (aliases) => castArray(aliases).indexOf(key) !== -1); | 
|  | } | 
|  |  | 
|  | function hasDefaultValue(key, value, defaults) { | 
|  | return value === defaults[key]; | 
|  | } | 
|  |  | 
|  | function isCamelCased(key, argv) { | 
|  | return /[A-Z]/.test(key) && camelCase(key) === key && // Is it camel case? | 
|  | argv[kebabCase(key)] != null; // Is the standard version defined? | 
|  | } | 
|  |  | 
|  | function keyToFlag(key) { | 
|  | return key.length === 1 ? `-${key}` : `--${key}`; | 
|  | } | 
|  |  | 
|  | function unparseOption(key, value, unparsed) { | 
|  | if (typeof value === 'string') { | 
|  | unparsed.push(keyToFlag(key), value); | 
|  | } else if (value === true) { | 
|  | unparsed.push(keyToFlag(key)); | 
|  | } else if (value === false) { | 
|  | unparsed.push(`--no-${key}`); | 
|  | } else if (Array.isArray(value)) { | 
|  | value.forEach((item) => unparseOption(key, item, unparsed)); | 
|  | } else if (isPlainObject(value)) { | 
|  | const flattened = flatten(value, { safe: true }); | 
|  |  | 
|  | for (const flattenedKey in flattened) { | 
|  | unparseOption(`${key}.${flattenedKey}`, flattened[flattenedKey], unparsed); | 
|  | } | 
|  | // Fallback case (numbers and other types) | 
|  | } else if (value != null) { | 
|  | unparsed.push(keyToFlag(key), `${value}`); | 
|  | } | 
|  | } | 
|  |  | 
|  | function unparsePositional(argv, options, unparsed) { | 
|  | const knownPositional = []; | 
|  |  | 
|  | // Unparse command if set, collecting all known positional arguments | 
|  | // e.g.: build <first> <second> <rest...> | 
|  | if (options.command) { | 
|  | const { 0: cmd, index } = options.command.match(/[^<[]*/); | 
|  | const { demanded, optional } = yargs() | 
|  | .getCommandInstance() | 
|  | .parseCommand(`foo ${options.command.substr(index + cmd.length)}`); | 
|  |  | 
|  | // Push command (can be a deep command) | 
|  | unparsed.push(...cmd.trim().split(/\s+/)); | 
|  |  | 
|  | // Push positional arguments | 
|  | [...demanded, ...optional].forEach(({ cmd: cmds, variadic }) => { | 
|  | knownPositional.push(...cmds); | 
|  |  | 
|  | const cmd = cmds[0]; | 
|  | const args = (variadic ? argv[cmd] || [] : [argv[cmd]]) | 
|  | .filter((arg) => arg != null) | 
|  | .map((arg) => `${arg}`); | 
|  |  | 
|  | unparsed.push(...args); | 
|  | }); | 
|  | } | 
|  |  | 
|  | // Unparse unkown positional arguments | 
|  | argv._ && unparsed.push(...argv._.slice(knownPositional.length)); | 
|  |  | 
|  | return knownPositional; | 
|  | } | 
|  |  | 
|  | function unparseOptions(argv, options, knownPositional, unparsed) { | 
|  | const optionsArgv = omitBy(argv, (value, key) => | 
|  | // Remove positional arguments | 
|  | knownPositional.includes(key) || | 
|  | // Remove special _, -- and $0 | 
|  | ['_', '--', '$0'].includes(key) || | 
|  | // Remove aliases | 
|  | isAlias(key, options.alias) || | 
|  | // Remove default values | 
|  | hasDefaultValue(key, value, options.default) || | 
|  | // Remove camel-cased | 
|  | isCamelCased(key, argv)); | 
|  |  | 
|  | for (const key in optionsArgv) { | 
|  | unparseOption(key, optionsArgv[key], unparsed); | 
|  | } | 
|  | } | 
|  |  | 
|  | function unparseEndOfOptions(argv, options, unparsed) { | 
|  | // Unparse ending (--) arguments if set | 
|  | argv['--'] && unparsed.push('--', ...argv['--']); | 
|  | } | 
|  |  | 
|  | // ------------------------------------------------------------ | 
|  |  | 
|  | function unparser(argv, options) { | 
|  | options = Object.assign({ | 
|  | alias: {}, | 
|  | default: {}, | 
|  | command: null, | 
|  | }, options); | 
|  |  | 
|  | const unparsed = []; | 
|  |  | 
|  | // Unparse known & unknown positional arguments (foo <first> <second> [rest...]) | 
|  | // All known positional will be returned so that they are not added as flags | 
|  | const knownPositional = unparsePositional(argv, options, unparsed); | 
|  |  | 
|  | // Unparse option arguments (--foo hello --bar hi) | 
|  | unparseOptions(argv, options, knownPositional, unparsed); | 
|  |  | 
|  | // Unparse "end-of-options" arguments (stuff after " -- ") | 
|  | unparseEndOfOptions(argv, options, unparsed); | 
|  |  | 
|  | return unparsed; | 
|  | } | 
|  |  | 
|  | module.exports = unparser; |