argument-parser/src/index.ts

44 lines
2 KiB
TypeScript

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[]) => (string[] | undefined),
): { fail: (errorMessage: string) => never, args: { [key: string]: string } } {
//Initialize state
const { outputArgs, shortToLongLookup, requiredOptions, fail } = initState(spec);
try {
const args = runPreParseHook({ args: process.argv.slice(2), preParseHook });
//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, 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 !== '') {
throw new Error(`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) {
throw new Error(`Missing option "${optName}" even though it is required.`);
}
}
} catch (error) {
fail((error as Error).message);
}
return {
fail,
args: outputArgs,
};
}