Search code examples
node.jses6-modulesyargs

How to pass arguments to Yargs commands at esm 'mode'?


I wrote a simple Node.js application that uses yargs commands and is built using CommonJS. It works as expected.

Now I'm trying to rewrite it to ESM.

The detailed code is provided at the end if needed.

In the CommonJS version, I passed parameters to the handler using the --flag=value flag after the command, and these values ended up in the params object in the command's handler function as a key:value pair.

It looked like this:

Command in the console:

node index add --someParam=some_param

Result in the handler:

{ ...add command...
 handler(params) {
  console.log(params) // { _: [ 'list' ], someParam: 'some_param', '$0': 'index' }
 }
}

However, in the ESM version, params always looks like:

{ _: [ 'add' ], '$0': 'index' }

Regardless of any additional flags.

The question is, how can I now pass arguments from the console to yargs commands?

Full code.


CommonJS version:

const yargs = require('yargs');
const chalk = require('chalk');
const {addNote, printNotes, deleteNote} = require("./notesController");

const add = {
  command: 'add',
  describe: 'Add new note to list',
  builder: {
    title: {
      type: 'string',
      describe: 'Note title',
      demandOption: true,
    }
  },
  handler(params) {
    console.log(params);
    const {title} = params;
    addNote(title);
    console.log(chalk.green(`${title} added to list`));
  },
};

yargs.command(add);

yargs.parse();

ESM version:

import yargs from 'yargs'
import chalk from 'chalk';
import { addNote, printNotes, deleteNote } from "./notesController.js";

const { green, red, bgRed } = chalk;

const add = {
 command: 'add',
 describe: 'Добавить новую заметку в список',
 builder: {
  title: {
   type: 'string',
   describe: 'Заголовок заметки',
   demandOption: true,
  }
 },
 handler(params) {
  addNote(params.title);
  console.log(chalk.green(`${params.title} added to list`));
 },
};
const commands = yargs(process.argv[2])
 .command(add)

commands.parse();

Solution

  • Solved the problem replacing

    const commands = yargs(process.argv[2])
         .command(add)
    

    with

    const commands = yargs(hideBin(process.argv))
         .command(add)
    

    Looks like by using direct process.argv[2] I had cut yargs from everything of the CLI (also the all the flags) except 2-nd index which was the command name. And thanks to whatever magic happens in the hideBin, now my commands gets all the flags correctly.

    Lesson: Use new tech by the devs book first, and only after you've done it correctly adapt it to your code. So you could find a difference between working and not-working cases.


    This answer was posted as an edit to the question How to pass arguments to Yargs commands at esm 'mode'? [Solved] by the OP Александр Каплан under CC BY-SA 4.0.