Skip to content

Instantly share code, notes, and snippets.

@rpivo
Last active December 18, 2020 16:20
Show Gist options
  • Save rpivo/0fec115ddbc2932c06f49487e963b332 to your computer and use it in GitHub Desktop.
Save rpivo/0fec115ddbc2932c06f49487e963b332 to your computer and use it in GitHub Desktop.
Using Custom CLI Parameters in Node

Using Custom CLI Parameters in Node

In the following TypeScript example, we're expecting two possible CLI parameters, --build and --port. We prepare a paramMap variable that has default values for all parameters, which are overwritten for each parameter that is manually passed in via the CLI.

See further down for a TypeScript example without comments as well as a JavaScript example.

// create an enum that contains each of the params
enum Params {
  BUILD = '--build',
  PORT = '--port',
}

// create a paramMap that's a Record type where the keys are Param enums, and their
// values are strings. paramMap is equal to the return value of Object.assign().
const paramMap: Record<Params, string> = Object.assign({}, {
    // We start with an empty object {} for Object.assign().
    // Then, we merge in an object containing default values for the params: 'dist' & '1000'.
    [Params.BUILD]: 'dist',
    [Params.PORT]: '1000',
  },
  // We then create an array from Node's process.argv array by slicing the first two items from the array
  // and getting the remaining items. Since process.argv always starts with 1) process.execPath (the
  // absolute pathname of the executable that started the Node process), and 2) the path of the
  // JavaScript file being executed, we can slice those arguments off, leaving us with just custom
  // arguments that the user passes in.

  // We then call reduce() on this array, taking each argument and splitting it into a key/value param.
  process.argv.slice(2).reduce((obj, param) => {
    const [key, value] = param.split('=');
    // If the key is in the Params enum, then we set this key & value on a new object.
    // Once the reduce is finished, it's passed in as the final object to Object.assign(), overwriting
    // default params.
    if (Object.values(Params).includes(key as Params)) obj[key] = value;
    return obj;
  }, {}),
);

// pull off the params to be used as local variables `build` & `port`
const {
  [Params.BUILD]: build,
  [Params.PORT]: port,
} = paramMap;

Without comments:

enum Params {
  BUILD = '--build',
  PORT = '--port',
}

const paramMap: Record<Params, string> = Object.assign({}, {
    [Params.BUILD]: 'dist',
    [Params.PORT]: '1000',
  },
  process.argv.slice(2).reduce((obj, param) => {
    const [key, value] = param.split('=');
    if (Object.values(Params).includes(key as Params)) obj[key] = value;
    return obj;
  }, {}),
);

const {
  [Params.BUILD]: build,
  [Params.PORT]: port,
} = paramMap;

Just JavaScript:

const Params = {
  BUILD: '--build',
  PORT: '--port',
};

const paramMap = Object.assign({}, {
    [Params.BUILD]: 'dist',
    [Params.PORT]: '1000',
  },
  process.argv.slice(2).reduce((obj, param) => {
    const [key, value] = param.split('=');
    if (Object.values(Params).includes(key)) obj[key] = value;
    return obj;
  }, {}),
);

const {
  [Params.BUILD]: build,
  [Params.PORT]: port,
} = paramMap;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment