import initState from './initState'; import IOption from './IOption'; import parseArgument from './parseArgument'; import runPreParseHook from './runPreParseHook'; /** * Checks the command line arguments against the given specification, and returns the arguments as a JavaScript object, as well as a failure function that prints the usage instructions before terminating. * If an error is found, outputs an error message and terminates with a non-zero exit code. * @param spec A specification of what arguments are expected. * @param preParseHook Optionally, a function to modify the command line arguments before parsing them. */ export default function parseArguments( spec: { [key: string]: IOption }, preParseHook?: (args: string[], fail: (message: string) => void) => (string[] | undefined), ): { fail: (errorMessage: string) => never, args: { [key: string]: string } } { //Initialize state const { outputArgs, shortToLongLookup, requiredOptions, fail } = initState(spec); const args = runPreParseHook({ args: process.argv.slice(2), preParseHook, fail }); //Iterate through all command line arguments. When we have read both name and value, verify the argument for correctness. //Show error if a name has no value afterwards, or a value has no name in front of it. const lastOption = args.reduce(parseArgument.bind(null, { spec, fail, outputArgs, requiredOptions, shortToLongLookup })); // argumentName must be cleared to '' after the value is read, so if it is not an empty string, the value was missing if (lastOption !== '') { return fail(`Option "${lastOption}" was not followed by a value.`); } //check if any entry in requiredArguments was not set for (const optName in requiredOptions) { if (spec.hasOwnProperty(optName) && requiredOptions[optName] === false) { return fail(`Missing option "${optName}" even though it is required.`); } } return { fail, args: outputArgs, }; }