-.- --. .-. --..

Node has native CLI argument parsing

I knew this was in the works, but wasn’t aware this was shipped with v16! (released in 2022). I was playing with TypeScript code transforms and wanted to update the source file after the transformation based on a flag. The script was basically standalone, so I didn’t want to depend on any external depedencies like argparse. The API I was aiming at was basically:

node enum-to-const-object.mjs source.ts [...]
node enum-to-const-object.mjs -w source.ts [...]
node enum-to-const-object.mjs --write source.ts [...]

The first invocation would print out the result to standard out, whereas the latter two would update the source file in-place, exactly how prettier works. The standard library API is pretty neat for such a simple interface:

// file: enum-to-const-object.mjs
// Note the mjs extension, which is why I'm able to use import. Otherwise,
// you'll have to use require in place of the following line
import { parseArgs } from 'node:util';

const options = {
	write: {
		type: 'boolean',
		short: 'w',
		default: false
	}
};

const { values, positionals } = parseArgs({ options, allowPositionals: true });
// values is of the shape { write: <flag value> }
// positionals: [ source.ts, ... ]

The options object is the one used by the parser as the configuration of the flags. The keys of this object are the expected flags in long-hand. The short property for each of these long-hand flags helps with adding aliases.

In addition to the flag format and strings, there is one more additional option that I had to configure: allowPositionals. This returns rest of the arguments that are not flags, which in my case are the files I wanted to transform. Once parseArgs is called using the configuration, and (by default) on process.argv, the flag values as an key-value pair, and the rest of the arguments are returned―values which contains the flag values, and positionals which contains the file list.

Docs Link