dist/parser.js
function parse(argv, options) {
    options = Object.assign({}, constants_1.PARSER_DEFAULTS, options);
    var _result = { _: [], __: [] };
    var _configs, _aliases, _indexed, _maxIndex;
    function handleError(message) {
        var args = [];
        for (var _i = 1; _i < arguments.length; _i++) {
            args[_i - 1] = arguments[_i];
        }
        var template = message;
        message = util_1.format.apply(void 0, [message].concat(args));
        var err = new Error(message);
        if (!options.onParserError)
            throw err;
        options.onParserError(err, template, args);
    }
    function getConfig(key) {
        // if (isType.string(key) && options.allowCamelcase)
        //   key = camelcase(<string>key);
        return _configs[_aliases[key]];
    }
    function castType(val, config) {
        var result = val;
        // This is a variadic value, iterate
        // each element and ensure type.
        if (Array.isArray(val)) {
            result = val.map(function (v) { return castType(v, config); });
        }
        else {
            if (config.type === 'boolean') {
                result = utils_1.toType.boolean(val);
            }
            else if (config.type === 'number') {
                result = utils_1.toType.number(val);
            }
            else if (config.type === 'array') {
                result = utils_1.toType.array(val);
            }
            else if (config.type === 'string') {
                result = utils_1.toType.string(val);
            }
            else if (utils_1.isLikeBoolean(val) && options.allowParseBooleans) {
                result = utils_1.toType.boolean(val);
            }
            else if (utils_1.isLikeNumber(val) && options.allowParseNumbers) {
                result = utils_1.toType.number(val);
            }
            else {
                result = utils_1.toType.string(val);
            }
        }
        return result;
    }
    function normalize() {
        var aliasMap = {};
        var variadicKeys = [];
        var indexKeys = [];
        var configs = options.options;
        var _loop_2 = function (k) {
            if (utils_1.isType.string(configs[k])) {
                configs[k] = {
                    type: configs[k]
                };
            }
            var config = configs[k];
            configs[k]['name'] = configs[k]['name'] || k;
            config.type = config.type || 'string';
            // Ensure supported type.
            if (utils_1.hasOwn(config, 'type') && !~constants_1.SUPPORTED_TYPES.indexOf(config.type)) {
                handleError("Type %s is not in supported types of %s.", config.type, constants_1.SUPPORTED_TYPES.join(', '));
                return { value: false };
            }
            config.alias = utils_1.toType.array(config.alias);
            if (utils_1.hasOwn(config, 'index')) {
                // Can't have dupe configs at
                // the same index.
                if (~indexKeys.indexOf(config.index)) {
                    handleError("Removing %s with duplicate index %s, the configuration already exists.", k, config.index);
                    return { value: false };
                }
                aliasMap[k] = config.index;
                aliasMap[config.index] = k;
                indexKeys.push(config.index);
            }
            else {
                // Flags cannot be variadic.
                config.variadic = false;
            }
            if (config.variadic)
                variadicKeys.push(k);
            aliasMap[k] = k;
            configs[k].alias = config.alias.map(function (v) {
                v = utils_1.stripFlag(v, options.charNegate);
                aliasMap[v] = k; // update all aliases.
                return v;
            });
        };
        for (var k in configs) {
            var state_1 = _loop_2(k);
            if (typeof state_1 === "object")
                return state_1.value;
        }
        return {
            aliasMap: aliasMap,
            indexKeys: indexKeys,
            configs: configs
        };
    }
    function breakoutArg(arg) {
        if (utils_1.isType.number(arg))
            return {
                key: arg,
                value: null
            };
        var hasFlag = utils_1.isFlag(arg);
        if (hasFlag)
            arg = utils_1.stripFlag(arg, options.charNegate);
        else
            arg = utils_1.stripVariadic(arg, options.charVariadic);
        var split = arg.split('=');
        if (hasFlag && options.allowCamelcase)
            split[0] = utils_1.toCamelcase(split[0]);
        return {
            key: split[0],
            value: split[1] || null
        };
    }
    function parseArg(arg, arr, i) {
        arg = arg + '';
        var hasFlag = utils_1.isFlag(arg);
        var hasSplit = ~arg.indexOf('=');
        var hasFlagShort = utils_1.isFlagShort(arg);
        var hasNegate = utils_1.isNegateFlag(arg, options.charNegate);
        var hasCount = utils_1.isFlagCount(arg);
        var hasDotNotation = utils_1.isDotNotationFlag(arg);
        var next = (arr[i + 1]) + '';
        var nextHasFlag = utils_1.isFlag(next);
        var nextHasCount = utils_1.isFlagCount(next);
        var nextHasVariadic = next.endsWith(options.charVariadic);
        var isLast = i === (arr.length - 1);
        // CHECK ENABLED //
        if (!options.allowCountOptions) {
            hasCount = false;
            nextHasCount = false;
        }
        if (!options.allowBoolNegation) {
            hasNegate = false;
        }
        if (!options.allowVariadics) {
            nextHasVariadic = false;
        }
        // BREAKOUT KEY //
        var x = _aliases;
        var keyVal = breakoutArg(arg);
        var key = _aliases[keyVal.key] || keyVal.key;
        var value = keyVal.value;
        // LOOKUP CONFIG //
        var idx = !_result._.length ? 0 : _result._.length;
        var confKey = !hasFlag ? idx : key;
        var config = getConfig(confKey) || { anon: true };
        // CHECK BOOL //
        var flagIsBool = (hasFlag && !hasCount && !hasSplit) && (nextHasFlag || nextHasVariadic || config.type === 'boolean' || isLast);
        // If a flag and a type is specified it's not boolean.
        if (hasFlag && config.type && config.type !== 'boolean')
            flagIsBool = false;
        // CHECK IF FLAG VALUE //
        // Should check current config for bool in iteration.
        var hasFlagValue = hasFlag && (!nextHasFlag && !nextHasCount && !nextHasVariadic && !isLast && !hasCount && !keyVal.value && config.type !== 'boolean');
        // CHECK SHORT VALUES //
        if (hasFlagShort && !options.allowShortValues) {
            hasFlagValue = false;
            if (!hasCount)
                flagIsBool = true;
        }
        // CHECK VARIADIC //
        var hasVariadic;
        var configVariadic = utils_1.isTruthyVariadic(config.variadic);
        // Check if variadic if enabled, allow config.variadic to override option.
        if (options.allowVariadics) {
            // Can't have variadics with flags.
            hasVariadic = !hasFlag &&
                (arg.endsWith(options.charVariadic) || configVariadic);
            // Update the config.
            if (hasVariadic)
                config.variadic = config.variadic || true;
        }
        else {
            // Ensure variadic is disabled in config.
            config.variadic = false;
        }
        // CHECK SHOULD INGEST //
        var shouldIngest = hasFlagValue || hasVariadic;
        var ingestable = !hasFlag && !hasVariadic && !utils_1.hasOwn(config, 'index');
        // CHECK CAMELCASE //
        // Check key for camelcase.
        if (options.allowCamelcase && hasFlag && utils_1.isType.string(key) && !hasDotNotation)
            key = chek_1.camelcase(key);
        // NORMALIZE KEY & VALUE //
        if (hasFlag) {
            // This is a boolean flag --force or -f
            // or is boolean negate --no-force or --no-f.
            if (flagIsBool) {
                value = hasNegate ? false : true;
            }
            // Flag like -vvvvv such as indicating level verbosity.
            // results in { v: 5 }
            else if (hasCount) {
                value = key.length;
                key = key[0];
            }
        }
        // This is a standard arg set key to it's index.
        else {
            value = key;
            key = idx;
        }
        return {
            index: i,
            key: key,
            value: value,
            isFlag: hasFlag,
            isFlagNegate: hasNegate,
            isFlagBool: flagIsBool,
            isFlagWithValue: hasFlagValue,
            isVariadic: hasVariadic,
            ingest: shouldIngest,
            ingestable: ingestable,
            config: config
        };
    }
    function reorderArgs(arr) {
        // If no indexed args reorder not needed.
        if (!_indexed.length)
            return arr;
        // Previous argument.
        var prev = parseArg(arr[0], arr, 0);
        // Reduce array and reorder for parsing.
        var reordered = arr.reduce(function (a, c, i) {
            if (c === '')
                return a;
            var parsed = parseArg(c, arr, i);
            if (!parsed.isFlag && !prev.isFlagWithValue)
                a.indexed.push(c);
            else
                a.remainder.push(c);
            prev = parsed;
            return a;
        }, { indexed: [], remainder: [] });
        return reordered.indexed.concat(reordered.remainder);
    }
    function setArg(key, val, config) {
        var cur;
        // Duplicate options are disabled.
        if (key && utils_1.hasOwn(_result, key) && !options.allowDuplicateOptions)
            return;
        if (key) {
            var getKey = utils_1.isType.number(key) ? "_[" + key + "]" : key;
            cur = chek_1.get(_result, getKey);
            // If exists ensure is array if
            // duplicate values are allowed.
            if (cur && !Array.isArray(cur) && options.allowDuplicateOptions)
                cur = [cur];
        }
        val = castType(val, config);
        if (Array.isArray(cur)) {
            cur.push(val);
            val = chek_1.flatten(cur);
        }
        if (utils_1.isType.number(key))
            _result._.push(val);
        else if (options.allowDotNotation)
            chek_1.set(_result, key, val);
        else
            _result[key] = val;
    }
    function ingest(arr, i, parsed) {
        // const result = parsed.value ? [parsed.value] : [];
        var result = [];
        // If not flag with value adjust index.
        if (!parsed.isFlagWithValue)
            result.push(parsed.value);
        // The primary configuration.
        var config = parsed.config;
        // Counter used when variadic has specified count.
        var ctr = result.length;
        // Holds current index.
        var n;
        // Variadic specifies a specific count.
        var count = utils_1.isType.number(config.variadic) ? config.variadic : null;
        // Otherwise ingest args until max count or reaches
        // another flag, negate or variadic.
        for (n = i + 1; n < arr.length; n++) {
            var arg = arr[n] + '';
            var ingestable = !utils_1.isFlag(arg) &&
                !arg.endsWith(options.charVariadic) &&
                (count === null || ctr < count);
            // If hit should eat arg don't break
            // unless it's past the first.
            if (!ingestable)
                break;
            result.push(utils_1.stripTokens(arg, options.charNegate, options.charVariadic));
            ctr += 1;
        }
        n = parsed.isFlagWithValue ? n - 1 : i + (ctr - 1);
        return {
            i: Math.max(0, n),
            val: !parsed.isVariadic ? result[0] : result
        };
    }
    // Normalize any option configurations.
    var normalized = normalize();
    // Errored normalizing abort.
    if (!normalized)
        return;
    _configs = normalized.configs;
    _aliases = normalized.aliasMap;
    _indexed = normalized.indexKeys;
    _maxIndex = Math.max.apply(Math, _indexed);
    if (utils_1.isType.string(argv))
        argv = argv.trim();
    // Use provided argv or use process args.
    argv = argv || process.argv.slice(2);
    // Expand args into an array.
    argv = utils_1.expandArgs(argv);
    // Check if has abort flag if true slice
    // array and store in abort array.
    var abortIdx = argv.indexOf('--');
    if (~abortIdx) {
        _result.__ = argv.slice(abortIdx + 1);
        argv = argv.slice(0, abortIdx);
    }
    // short options -f are allowed can exapand. -abc >> -a -b -c.
    if (options.allowShortExpand)
        argv = utils_1.expandOptions(argv, options.allowShortValues);
    // Reorder the arguments so that
    // install --force /some/path becomes
    // install /some/path --force.
    argv = reorderArgs(argv);
    // PARSE ARGUMENTS //
    for (var i = 0; i < argv.length; i++) {
        var k = argv[i];
        // Parse the argument returning helpers.
        var parsed = parseArg(k, argv, i);
        // Anonymous flags/args are not allowed.
        if (!options.allowAnonymous && parsed.config.anon) {
            var label = parsed.isFlag ? 'Flag' : 'Argument';
            handleError("%s %s failed: invalidated by anonymous prohibited (value: %s).", label, parsed.key, parsed.value);
            break;
        }
        if (parsed.ingest) {
            var tmp = ingest(argv, i, parsed);
            i = tmp.i;
            setArg(parsed.key, tmp.val, parsed.config);
        }
        else {
            // This happens when we've used the next arg
            // as this flag's value so we increment.
            setArg(parsed.key, parsed.value, parsed.config);
        }
    }
    var _loop_1 = function (k) {
        var config = _configs[k];
        config = config;
        var hasIndex = utils_1.hasOwn(config, 'index');
        var exists = hasIndex ? !chek_1.isUndefined(_result._[config.index]) : chek_1.has(_result, k);
        // HANDLE DEFAULTS //
        var curVal = hasIndex ? _result._[config.index] : chek_1.get(_result, k);
        var normalVal = utils_1.ensureDefault(curVal, castType(config.default, config));
        // If exists normalize and ensure
        // the default value.
        if (exists) {
            if (hasIndex)
                _result._[config.index] = normalVal;
            else
                chek_1.set(_result, k, normalVal);
        }
        // Otherwise check if placeholders are enabled.
        else {
            if (hasIndex && options.allowPlaceholderArgs)
                _result._[config.index] = normalVal === !chek_1.isValue(normalVal) || normalVal === '' ? null : normalVal;
            else if (options.allowPlaceholderOptions)
                chek_1.set(_result, k, normalVal);
        }
        // HANDLE ALIASES //
        // When parsing from Kawkah we'll handle aliases there.
        if (utils_1.hasOwn(config, 'alias') && options.allowAliases) {
            var aliases = !Array.isArray(config.alias) ? [config.alias] : config.alias;
            // Update object with aliases.
            aliases.forEach(function (a) {
                if (exists || options.allowPlaceholderOptions)
                    _result[a] = chek_1.get(_result, k);
            });
        }
        // HANDLE EXTEND ARGS //
        if (options.allowExtendArgs && hasIndex)
            _result[k] = _result._[config.index];
    };
    // DEFAULTS, EXTEND ALIASES & ARGS //
    for (var k in _configs) {
        _loop_1(k);
    }
    // When allow placeholders are enabled ensures that we
    // don't end up with undefined or empty array elements.
    if (options.allowPlaceholderArgs) {
        var ctr = 0;
        while (ctr < _maxIndex) {
            if (chek_1.isUndefined(_result._[ctr]))
                _result._[ctr] = null;
            ctr++;
        }
    }
    return _result;
}
function parse(argv, options) {
    options = Object.assign({}, constants_1.PARSER_DEFAULTS, options);
    var _result = { _: [], __: [] };
    var _configs, _aliases, _indexed, _maxIndex;
    function handleError(message) {
        var args = [];
        for (var _i = 1; _i < arguments.length; _i++) {
            args[_i - 1] = arguments[_i];
        }
        var template = message;
        message = util_1.format.apply(void 0, [message].concat(args));
        var err = new Error(message);
        if (!options.onParserError)
            throw err;
        options.onParserError(err, template, args);
    }
    function getConfig(key) {
        // if (isType.string(key) && options.allowCamelcase)
        //   key = camelcase(<string>key);
        return _configs[_aliases[key]];
    }
    function castType(val, config) {
        var result = val;
        // This is a variadic value, iterate
        // each element and ensure type.
        if (Array.isArray(val)) {
            result = val.map(function (v) { return castType(v, config); });
        }
        else {
            if (config.type === 'boolean') {
                result = utils_1.toType.boolean(val);
            }
            else if (config.type === 'number') {
                result = utils_1.toType.number(val);
            }
            else if (config.type === 'array') {
                result = utils_1.toType.array(val);
            }
            else if (config.type === 'string') {
                result = utils_1.toType.string(val);
            }
            else if (utils_1.isLikeBoolean(val) && options.allowParseBooleans) {
                result = utils_1.toType.boolean(val);
            }
            else if (utils_1.isLikeNumber(val) && options.allowParseNumbers) {
                result = utils_1.toType.number(val);
            }
            else {
                result = utils_1.toType.string(val);
            }
        }
        return result;
    }
    function normalize() {
        var aliasMap = {};
        var variadicKeys = [];
        var indexKeys = [];
        var configs = options.options;
        var _loop_2 = function (k) {
            if (utils_1.isType.string(configs[k])) {
                configs[k] = {
                    type: configs[k]
                };
            }
            var config = configs[k];
            configs[k]['name'] = configs[k]['name'] || k;
            config.type = config.type || 'string';
            // Ensure supported type.
            if (utils_1.hasOwn(config, 'type') && !~constants_1.SUPPORTED_TYPES.indexOf(config.type)) {
                handleError("Type %s is not in supported types of %s.", config.type, constants_1.SUPPORTED_TYPES.join(', '));
                return { value: false };
            }
            config.alias = utils_1.toType.array(config.alias);
            if (utils_1.hasOwn(config, 'index')) {
                // Can't have dupe configs at
                // the same index.
                if (~indexKeys.indexOf(config.index)) {
                    handleError("Removing %s with duplicate index %s, the configuration already exists.", k, config.index);
                    return { value: false };
                }
                aliasMap[k] = config.index;
                aliasMap[config.index] = k;
                indexKeys.push(config.index);
            }
            else {
                // Flags cannot be variadic.
                config.variadic = false;
            }
            if (config.variadic)
                variadicKeys.push(k);
            aliasMap[k] = k;
            configs[k].alias = config.alias.map(function (v) {
                v = utils_1.stripFlag(v, options.charNegate);
                aliasMap[v] = k; // update all aliases.
                return v;
            });
        };
        for (var k in configs) {
            var state_1 = _loop_2(k);
            if (typeof state_1 === "object")
                return state_1.value;
        }
        return {
            aliasMap: aliasMap,
            indexKeys: indexKeys,
            configs: configs
        };
    }
    function breakoutArg(arg) {
        if (utils_1.isType.number(arg))
            return {
                key: arg,
                value: null
            };
        var hasFlag = utils_1.isFlag(arg);
        if (hasFlag)
            arg = utils_1.stripFlag(arg, options.charNegate);
        else
            arg = utils_1.stripVariadic(arg, options.charVariadic);
        var split = arg.split('=');
        if (hasFlag && options.allowCamelcase)
            split[0] = utils_1.toCamelcase(split[0]);
        return {
            key: split[0],
            value: split[1] || null
        };
    }
    function parseArg(arg, arr, i) {
        arg = arg + '';
        var hasFlag = utils_1.isFlag(arg);
        var hasSplit = ~arg.indexOf('=');
        var hasFlagShort = utils_1.isFlagShort(arg);
        var hasNegate = utils_1.isNegateFlag(arg, options.charNegate);
        var hasCount = utils_1.isFlagCount(arg);
        var hasDotNotation = utils_1.isDotNotationFlag(arg);
        var next = (arr[i + 1]) + '';
        var nextHasFlag = utils_1.isFlag(next);
        var nextHasCount = utils_1.isFlagCount(next);
        var nextHasVariadic = next.endsWith(options.charVariadic);
        var isLast = i === (arr.length - 1);
        // CHECK ENABLED //
        if (!options.allowCountOptions) {
            hasCount = false;
            nextHasCount = false;
        }
        if (!options.allowBoolNegation) {
            hasNegate = false;
        }
        if (!options.allowVariadics) {
            nextHasVariadic = false;
        }
        // BREAKOUT KEY //
        var x = _aliases;
        var keyVal = breakoutArg(arg);
        var key = _aliases[keyVal.key] || keyVal.key;
        var value = keyVal.value;
        // LOOKUP CONFIG //
        var idx = !_result._.length ? 0 : _result._.length;
        var confKey = !hasFlag ? idx : key;
        var config = getConfig(confKey) || { anon: true };
        // CHECK BOOL //
        var flagIsBool = (hasFlag && !hasCount && !hasSplit) && (nextHasFlag || nextHasVariadic || config.type === 'boolean' || isLast);
        // If a flag and a type is specified it's not boolean.
        if (hasFlag && config.type && config.type !== 'boolean')
            flagIsBool = false;
        // CHECK IF FLAG VALUE //
        // Should check current config for bool in iteration.
        var hasFlagValue = hasFlag && (!nextHasFlag && !nextHasCount && !nextHasVariadic && !isLast && !hasCount && !keyVal.value && config.type !== 'boolean');
        // CHECK SHORT VALUES //
        if (hasFlagShort && !options.allowShortValues) {
            hasFlagValue = false;
            if (!hasCount)
                flagIsBool = true;
        }
        // CHECK VARIADIC //
        var hasVariadic;
        var configVariadic = utils_1.isTruthyVariadic(config.variadic);
        // Check if variadic if enabled, allow config.variadic to override option.
        if (options.allowVariadics) {
            // Can't have variadics with flags.
            hasVariadic = !hasFlag &&
                (arg.endsWith(options.charVariadic) || configVariadic);
            // Update the config.
            if (hasVariadic)
                config.variadic = config.variadic || true;
        }
        else {
            // Ensure variadic is disabled in config.
            config.variadic = false;
        }
        // CHECK SHOULD INGEST //
        var shouldIngest = hasFlagValue || hasVariadic;
        var ingestable = !hasFlag && !hasVariadic && !utils_1.hasOwn(config, 'index');
        // CHECK CAMELCASE //
        // Check key for camelcase.
        if (options.allowCamelcase && hasFlag && utils_1.isType.string(key) && !hasDotNotation)
            key = chek_1.camelcase(key);
        // NORMALIZE KEY & VALUE //
        if (hasFlag) {
            // This is a boolean flag --force or -f
            // or is boolean negate --no-force or --no-f.
            if (flagIsBool) {
                value = hasNegate ? false : true;
            }
            // Flag like -vvvvv such as indicating level verbosity.
            // results in { v: 5 }
            else if (hasCount) {
                value = key.length;
                key = key[0];
            }
        }
        // This is a standard arg set key to it's index.
        else {
            value = key;
            key = idx;
        }
        return {
            index: i,
            key: key,
            value: value,
            isFlag: hasFlag,
            isFlagNegate: hasNegate,
            isFlagBool: flagIsBool,
            isFlagWithValue: hasFlagValue,
            isVariadic: hasVariadic,
            ingest: shouldIngest,
            ingestable: ingestable,
            config: config
        };
    }
    function reorderArgs(arr) {
        // If no indexed args reorder not needed.
        if (!_indexed.length)
            return arr;
        // Previous argument.
        var prev = parseArg(arr[0], arr, 0);
        // Reduce array and reorder for parsing.
        var reordered = arr.reduce(function (a, c, i) {
            if (c === '')
                return a;
            var parsed = parseArg(c, arr, i);
            if (!parsed.isFlag && !prev.isFlagWithValue)
                a.indexed.push(c);
            else
                a.remainder.push(c);
            prev = parsed;
            return a;
        }, { indexed: [], remainder: [] });
        return reordered.indexed.concat(reordered.remainder);
    }
    function setArg(key, val, config) {
        var cur;
        // Duplicate options are disabled.
        if (key && utils_1.hasOwn(_result, key) && !options.allowDuplicateOptions)
            return;
        if (key) {
            var getKey = utils_1.isType.number(key) ? "_[" + key + "]" : key;
            cur = chek_1.get(_result, getKey);
            // If exists ensure is array if
            // duplicate values are allowed.
            if (cur && !Array.isArray(cur) && options.allowDuplicateOptions)
                cur = [cur];
        }
        val = castType(val, config);
        if (Array.isArray(cur)) {
            cur.push(val);
            val = chek_1.flatten(cur);
        }
        if (utils_1.isType.number(key))
            _result._.push(val);
        else if (options.allowDotNotation)
            chek_1.set(_result, key, val);
        else
            _result[key] = val;
    }
    function ingest(arr, i, parsed) {
        // const result = parsed.value ? [parsed.value] : [];
        var result = [];
        // If not flag with value adjust index.
        if (!parsed.isFlagWithValue)
            result.push(parsed.value);
        // The primary configuration.
        var config = parsed.config;
        // Counter used when variadic has specified count.
        var ctr = result.length;
        // Holds current index.
        var n;
        // Variadic specifies a specific count.
        var count = utils_1.isType.number(config.variadic) ? config.variadic : null;
        // Otherwise ingest args until max count or reaches
        // another flag, negate or variadic.
        for (n = i + 1; n < arr.length; n++) {
            var arg = arr[n] + '';
            var ingestable = !utils_1.isFlag(arg) &&
                !arg.endsWith(options.charVariadic) &&
                (count === null || ctr < count);
            // If hit should eat arg don't break
            // unless it's past the first.
            if (!ingestable)
                break;
            result.push(utils_1.stripTokens(arg, options.charNegate, options.charVariadic));
            ctr += 1;
        }
        n = parsed.isFlagWithValue ? n - 1 : i + (ctr - 1);
        return {
            i: Math.max(0, n),
            val: !parsed.isVariadic ? result[0] : result
        };
    }
    // Normalize any option configurations.
    var normalized = normalize();
    // Errored normalizing abort.
    if (!normalized)
        return;
    _configs = normalized.configs;
    _aliases = normalized.aliasMap;
    _indexed = normalized.indexKeys;
    _maxIndex = Math.max.apply(Math, _indexed);
    if (utils_1.isType.string(argv))
        argv = argv.trim();
    // Use provided argv or use process args.
    argv = argv || process.argv.slice(2);
    // Expand args into an array.
    argv = utils_1.expandArgs(argv);
    // Check if has abort flag if true slice
    // array and store in abort array.
    var abortIdx = argv.indexOf('--');
    if (~abortIdx) {
        _result.__ = argv.slice(abortIdx + 1);
        argv = argv.slice(0, abortIdx);
    }
    // short options -f are allowed can exapand. -abc >> -a -b -c.
    if (options.allowShortExpand)
        argv = utils_1.expandOptions(argv, options.allowShortValues);
    // Reorder the arguments so that
    // install --force /some/path becomes
    // install /some/path --force.
    argv = reorderArgs(argv);
    // PARSE ARGUMENTS //
    for (var i = 0; i < argv.length; i++) {
        var k = argv[i];
        // Parse the argument returning helpers.
        var parsed = parseArg(k, argv, i);
        // Anonymous flags/args are not allowed.
        if (!options.allowAnonymous && parsed.config.anon) {
            var label = parsed.isFlag ? 'Flag' : 'Argument';
            handleError("%s %s failed: invalidated by anonymous prohibited (value: %s).", label, parsed.key, parsed.value);
            break;
        }
        if (parsed.ingest) {
            var tmp = ingest(argv, i, parsed);
            i = tmp.i;
            setArg(parsed.key, tmp.val, parsed.config);
        }
        else {
            // This happens when we've used the next arg
            // as this flag's value so we increment.
            setArg(parsed.key, parsed.value, parsed.config);
        }
    }
    var _loop_1 = function (k) {
        var config = _configs[k];
        config = config;
        var hasIndex = utils_1.hasOwn(config, 'index');
        var exists = hasIndex ? !chek_1.isUndefined(_result._[config.index]) : chek_1.has(_result, k);
        // HANDLE DEFAULTS //
        var curVal = hasIndex ? _result._[config.index] : chek_1.get(_result, k);
        var normalVal = utils_1.ensureDefault(curVal, castType(config.default, config));
        // If exists normalize and ensure
        // the default value.
        if (exists) {
            if (hasIndex)
                _result._[config.index] = normalVal;
            else
                chek_1.set(_result, k, normalVal);
        }
        // Otherwise check if placeholders are enabled.
        else {
            if (hasIndex && options.allowPlaceholderArgs)
                _result._[config.index] = normalVal === !chek_1.isValue(normalVal) || normalVal === '' ? null : normalVal;
            else if (options.allowPlaceholderOptions)
                chek_1.set(_result, k, normalVal);
        }
        // HANDLE ALIASES //
        // When parsing from Kawkah we'll handle aliases there.
        if (utils_1.hasOwn(config, 'alias') && options.allowAliases) {
            var aliases = !Array.isArray(config.alias) ? [config.alias] : config.alias;
            // Update object with aliases.
            aliases.forEach(function (a) {
                if (exists || options.allowPlaceholderOptions)
                    _result[a] = chek_1.get(_result, k);
            });
        }
        // HANDLE EXTEND ARGS //
        if (options.allowExtendArgs && hasIndex)
            _result[k] = _result._[config.index];
    };
    // DEFAULTS, EXTEND ALIASES & ARGS //
    for (var k in _configs) {
        _loop_1(k);
    }
    // When allow placeholders are enabled ensures that we
    // don't end up with undefined or empty array elements.
    if (options.allowPlaceholderArgs) {
        var ctr = 0;
        while (ctr < _maxIndex) {
            if (chek_1.isUndefined(_result._[ctr]))
                _result._[ctr] = null;
            ctr++;
        }
    }
    return _result;
}
function parse ( argv , options ) { options = Object . assign ( { } , constants_1 . PARSER_DEFAULTS , options ) ; var _result = { _ : [ ] , __ : [ ] } ; var _configs , _aliases , _indexed , _maxIndex ; function handleError ( message ) { var args = [ ] ; for ( var _i = 1 ; _i < arguments . length ; _i ++ ) { args [ _i - 1 ] = arguments [ _i ] ; } var template = message ; message = util_1 . format . apply ( void 0 , [ message ] . concat ( args ) ) ; var err = new Error ( message ) ; if ( ! options . onParserError ) throw err ; options . onParserError ( err , template , args ) ; } function getConfig ( key ) { // if (isType.string(key) && options.allowCamelcase) //   key = camelcase(<string>key); return _configs [ _aliases [ key ] ] ; } function castType ( val , config ) { var result = val ; // This is a variadic value, iterate // each element and ensure type. if ( Array . isArray ( val ) ) { result = val . map ( function ( v ) { return castType ( v , config ) ; } ) ; } else { if ( config . type === 'boolean' ) { result = utils_1 . toType . boolean ( val ) ; } else if ( config . type === 'number' ) { result = utils_1 . toType . number ( val ) ; } else if ( config . type === 'array' ) { result = utils_1 . toType . array ( val ) ; } else if ( config . type === 'string' ) { result = utils_1 . toType . string ( val ) ; } else if ( utils_1 . isLikeBoolean ( val ) && options . allowParseBooleans ) { result = utils_1 . toType . boolean ( val ) ; } else if ( utils_1 . isLikeNumber ( val ) && options . allowParseNumbers ) { result = utils_1 . toType . number ( val ) ; } else { result = utils_1 . toType . string ( val ) ; } } return result ; } function normalize ( ) { var aliasMap = { } ; var variadicKeys = [ ] ; var indexKeys = [ ] ; var configs = options . options ; var _loop_2 = function ( k ) { if ( utils_1 . isType . string ( configs [ k ] ) ) { configs [ k ] = { type : configs [ k ] } ; } var config = configs [ k ] ; configs [ k ] [ 'name' ] = configs [ k ] [ 'name' ] || k ; config . type = config . type || 'string' ; // Ensure supported type. if ( utils_1 . hasOwn ( config , 'type' ) && ! ~ constants_1 . SUPPORTED_TYPES . indexOf ( config . type ) ) { handleError ( "Type %s is not in supported types of %s." , config . type , constants_1 . SUPPORTED_TYPES . join ( ', ' ) ) ; return { value : false } ; } config . alias = utils_1 . toType . array ( config . alias ) ; if ( utils_1 . hasOwn ( config , 'index' ) ) { // Can't have dupe configs at // the same index. if ( ~ indexKeys . indexOf ( config . index ) ) { handleError ( "Removing %s with duplicate index %s, the configuration already exists." , k , config . index ) ; return { value : false } ; } aliasMap [ k ] = config . index ; aliasMap [ config . index ] = k ; indexKeys . push ( config . index ) ; } else { // Flags cannot be variadic. config . variadic = false ; } if ( config . variadic ) variadicKeys . push ( k ) ; aliasMap [ k ] = k ; configs [ k ] . alias = config . alias . map ( function ( v ) { v = utils_1 . stripFlag ( v , options . charNegate ) ; aliasMap [ v ] = k ; // update all aliases. return v ; } ) ; } ; for ( var k in configs ) { var state_1 = _loop_2 ( k ) ; if ( typeof state_1 === "object" ) return state_1 . value ; } return { aliasMap : aliasMap , indexKeys : indexKeys , configs : configs } ; } function breakoutArg ( arg ) { if ( utils_1 . isType . number ( arg ) ) return { key : arg , value : null } ; var hasFlag = utils_1 . isFlag ( arg ) ; if ( hasFlag ) arg = utils_1 . stripFlag ( arg , options . charNegate ) ; else arg = utils_1 . stripVariadic ( arg , options . charVariadic ) ; var split = arg . split ( '=' ) ; if ( hasFlag && options . allowCamelcase ) split [ 0 ] = utils_1 . toCamelcase ( split [ 0 ] ) ; return { key : split [ 0 ] , value : split [ 1 ] || null } ; } function parseArg ( arg , arr , i ) { arg = arg + '' ; var hasFlag = utils_1 . isFlag ( arg ) ; var hasSplit = ~ arg . indexOf ( '=' ) ; var hasFlagShort = utils_1 . isFlagShort ( arg ) ; var hasNegate = utils_1 . isNegateFlag ( arg , options . charNegate ) ; var hasCount = utils_1 . isFlagCount ( arg ) ; var hasDotNotation = utils_1 . isDotNotationFlag ( arg ) ; var next = ( arr [ i + 1 ] ) + '' ; var nextHasFlag = utils_1 . isFlag ( next ) ; var nextHasCount = utils_1 . isFlagCount ( next ) ; var nextHasVariadic = next . endsWith ( options . charVariadic ) ; var isLast = i === ( arr . length - 1 ) ; // CHECK ENABLED // if ( ! options . allowCountOptions ) { hasCount = false ; nextHasCount = false ; } if ( ! options . allowBoolNegation ) { hasNegate = false ; } if ( ! options . allowVariadics ) { nextHasVariadic = false ; } // BREAKOUT KEY // var x = _aliases ; var keyVal = breakoutArg ( arg ) ; var key = _aliases [ keyVal . key ] || keyVal . key ; var value = keyVal . value ; // LOOKUP CONFIG // var idx = ! _result . _ . length ? 0 : _result . _ . length ; var confKey = ! hasFlag ? idx : key ; var config = getConfig ( confKey ) || { anon : true } ; // CHECK BOOL // var flagIsBool = ( hasFlag && ! hasCount && ! hasSplit ) && ( nextHasFlag || nextHasVariadic || config . type === 'boolean' || isLast ) ; // If a flag and a type is specified it's not boolean. if ( hasFlag && config . type && config . type !== 'boolean' ) flagIsBool = false ; // CHECK IF FLAG VALUE // // Should check current config for bool in iteration. var hasFlagValue = hasFlag && ( ! nextHasFlag && ! nextHasCount && ! nextHasVariadic && ! isLast && ! hasCount && ! keyVal . value && config . type !== 'boolean' ) ; // CHECK SHORT VALUES // if ( hasFlagShort && ! options . allowShortValues ) { hasFlagValue = false ; if ( ! hasCount ) flagIsBool = true ; } // CHECK VARIADIC // var hasVariadic ; var configVariadic = utils_1 . isTruthyVariadic ( config . variadic ) ; // Check if variadic if enabled, allow config.variadic to override option. if ( options . allowVariadics ) { // Can't have variadics with flags. hasVariadic = ! hasFlag && ( arg . endsWith ( options . charVariadic ) || configVariadic ) ; // Update the config. if ( hasVariadic ) config . variadic = config . variadic || true ; } else { // Ensure variadic is disabled in config. config . variadic = false ; } // CHECK SHOULD INGEST // var shouldIngest = hasFlagValue || hasVariadic ; var ingestable = ! hasFlag && ! hasVariadic && ! utils_1 . hasOwn ( config , 'index' ) ; // CHECK CAMELCASE // // Check key for camelcase. if ( options . allowCamelcase && hasFlag && utils_1 . isType . string ( key ) && ! hasDotNotation ) key = chek_1 . camelcase ( key ) ; // NORMALIZE KEY & VALUE // if ( hasFlag ) { // This is a boolean flag --force or -f // or is boolean negate --no-force or --no-f. if ( flagIsBool ) { value = hasNegate ? false : true ; } // Flag like -vvvvv such as indicating level verbosity. // results in { v: 5 } else if ( hasCount ) { value = key . length ; key = key [ 0 ] ; } } // This is a standard arg set key to it's index. else { value = key ; key = idx ; } return { index : i , key : key , value : value , isFlag : hasFlag , isFlagNegate : hasNegate , isFlagBool : flagIsBool , isFlagWithValue : hasFlagValue , isVariadic : hasVariadic , ingest : shouldIngest , ingestable : ingestable , config : config } ; } function reorderArgs ( arr ) { // If no indexed args reorder not needed. if ( ! _indexed . length ) return arr ; // Previous argument. var prev = parseArg ( arr [ 0 ] , arr , 0 ) ; // Reduce array and reorder for parsing. var reordered = arr . reduce ( function ( a , c , i ) { if ( c === '' ) return a ; var parsed = parseArg ( c , arr , i ) ; if ( ! parsed . isFlag && ! prev . isFlagWithValue ) a . indexed . push ( c ) ; else a . remainder . push ( c ) ; prev = parsed ; return a ; } , { indexed : [ ] , remainder : [ ] } ) ; return reordered . indexed . concat ( reordered . remainder ) ; } function setArg ( key , val , config ) { var cur ; // Duplicate options are disabled. if ( key && utils_1 . hasOwn ( _result , key ) && ! options . allowDuplicateOptions ) return ; if ( key ) { var getKey = utils_1 . isType . number ( key ) ? "_[" + key + "]" : key ; cur = chek_1 . get ( _result , getKey ) ; // If exists ensure is array if // duplicate values are allowed. if ( cur && ! Array . isArray ( cur ) && options . allowDuplicateOptions ) cur = [ cur ] ; } val = castType ( val , config ) ; if ( Array . isArray ( cur ) ) { cur . push ( val ) ; val = chek_1 . flatten ( cur ) ; } if ( utils_1 . isType . number ( key ) ) _result . _ . push ( val ) ; else if ( options . allowDotNotation ) chek_1 . set ( _result , key , val ) ; else _result [ key ] = val ; } function ingest ( arr , i , parsed ) { // const result = parsed.value ? [parsed.value] : []; var result = [ ] ; // If not flag with value adjust index. if ( ! parsed . isFlagWithValue ) result . push ( parsed . value ) ; // The primary configuration. var config = parsed . config ; // Counter used when variadic has specified count. var ctr = result . length ; // Holds current index. var n ; // Variadic specifies a specific count. var count = utils_1 . isType . number ( config . variadic ) ? config . variadic : null ; // Otherwise ingest args until max count or reaches // another flag, negate or variadic. for ( n = i + 1 ; n < arr . length ; n ++ ) { var arg = arr [ n ] + '' ; var ingestable = ! utils_1 . isFlag ( arg ) && ! arg . endsWith ( options . charVariadic ) && ( count === null || ctr < count ) ; // If hit should eat arg don't break // unless it's past the first. if ( ! ingestable ) break ; result . push ( utils_1 . stripTokens ( arg , options . charNegate , options . charVariadic ) ) ; ctr += 1 ; } n = parsed . isFlagWithValue ? n - 1 : i + ( ctr - 1 ) ; return { i : Math . max ( 0 , n ) , val : ! parsed . isVariadic ? result [ 0 ] : result } ; } // Normalize any option configurations. var normalized = normalize ( ) ; // Errored normalizing abort. if ( ! normalized ) return ; _configs = normalized . configs ; _aliases = normalized . aliasMap ; _indexed = normalized . indexKeys ; _maxIndex = Math . max . apply ( Math , _indexed ) ; if ( utils_1 . isType . string ( argv ) ) argv = argv . trim ( ) ; // Use provided argv or use process args. argv = argv || process . argv . slice ( 2 ) ; // Expand args into an array. argv = utils_1 . expandArgs ( argv ) ; // Check if has abort flag if true slice // array and store in abort array. var abortIdx = argv . indexOf ( '--' ) ; if ( ~ abortIdx ) { _result . __ = argv . slice ( abortIdx + 1 ) ; argv = argv . slice ( 0 , abortIdx ) ; } // short options -f are allowed can exapand. -abc >> -a -b -c. if ( options . allowShortExpand ) argv = utils_1 . expandOptions ( argv , options . allowShortValues ) ; // Reorder the arguments so that // install --force /some/path becomes // install /some/path --force. argv = reorderArgs ( argv ) ; // PARSE ARGUMENTS // for ( var i = 0 ; i < argv . length ; i ++ ) { var k = argv [ i ] ; // Parse the argument returning helpers. var parsed = parseArg ( k , argv , i ) ; // Anonymous flags/args are not allowed. if ( ! options . allowAnonymous && parsed . config . anon ) { var label = parsed . isFlag ? 'Flag' : 'Argument' ; handleError ( "%s %s failed: invalidated by anonymous prohibited (value: %s)." , label , parsed . key , parsed . value ) ; break ; } if ( parsed . ingest ) { var tmp = ingest ( argv , i , parsed ) ; i = tmp . i ; setArg ( parsed . key , tmp . val , parsed . config ) ; } else { // This happens when we've used the next arg // as this flag's value so we increment. setArg ( parsed . key , parsed . value , parsed . config ) ; } } var _loop_1 = function ( k ) { var config = _configs [ k ] ; config = config ; var hasIndex = utils_1 . hasOwn ( config , 'index' ) ; var exists = hasIndex ? ! chek_1 . isUndefined ( _result . _ [ config . index ] ) : chek_1 . has ( _result , k ) ; // HANDLE DEFAULTS // var curVal = hasIndex ? _result . _ [ config . index ] : chek_1 . get ( _result , k ) ; var normalVal = utils_1 . ensureDefault ( curVal , castType ( config . default , config ) ) ; // If exists normalize and ensure // the default value. if ( exists ) { if ( hasIndex ) _result . _ [ config . index ] = normalVal ; else chek_1 . set ( _result , k , normalVal ) ; } // Otherwise check if placeholders are enabled. else { if ( hasIndex && options . allowPlaceholderArgs ) _result . _ [ config . index ] = normalVal === ! chek_1 . isValue ( normalVal ) || normalVal === '' ? null : normalVal ; else if ( options . allowPlaceholderOptions ) chek_1 . set ( _result , k , normalVal ) ; } // HANDLE ALIASES // // When parsing from Kawkah we'll handle aliases there. if ( utils_1 . hasOwn ( config , 'alias' ) && options . allowAliases ) { var aliases = ! Array . isArray ( config . alias ) ? [ config . alias ] : config . alias ; // Update object with aliases. aliases . forEach ( function ( a ) { if ( exists || options . allowPlaceholderOptions ) _result [ a ] = chek_1 . get ( _result , k ) ; } ) ; } // HANDLE EXTEND ARGS // if ( options . allowExtendArgs && hasIndex ) _result [ k ] = _result . _ [ config . index ] ; } ; // DEFAULTS, EXTEND ALIASES & ARGS // for ( var k in _configs ) { _loop_1 ( k ) ; } // When allow placeholders are enabled ensures that we // don't end up with undefined or empty array elements. if ( options . allowPlaceholderArgs ) { var ctr = 0 ; while ( ctr < _maxIndex ) { if ( chek_1 . isUndefined ( _result . _ [ ctr ] ) ) _result . _ [ ctr ] = null ; ctr ++ ; } } return _result ; }
Parses provided arguments or uses process.argv.

@example .parse('install /some/path --force);
@example .parse('sip show log -vvvvv) >> { v: 5 }
@example .parse('--user.name=Jim') >> { user: { name: 'Jim' } }

@param argv string or array to be parsed.
@param options parser options.
Parses provided arguments or uses process . argv .