lukeed/mri

Boolean and string argument with no value is not parsed as true

bluwy opened this issue · 0 comments

When I have a config like { boolean: ["foo"], string: ["foo"] }, I expect that passing --foo (without any values) to return true in the parsed object. Below shows the exact scenario:

import mri from "mri";

const opts = { boolean: ["foo"], string: ["foo"] };

// ❓ cmd --foo
console.log(mri(["--foo"], opts));
// => { _: [], foo: '' }
// Expected: { _: [], foo: true }

// ❓ cmd --foo --bar
console.log(mri(["--foo", "--bar"], opts));
// => { _: [], foo: '', bar: true }
// Expected: { _: [], foo: true, bar: true }

// ✅ cmd --foo ""
console.log(mri(["--foo", ""], opts));
// => { _: [], foo: '' }

// ✅ cmd --foo "" --bar
console.log(mri(["--foo", "", "--bar"], opts));
// => { _: [], foo: '', bar: true }

// ✅ cmd --foo "str"
console.log(mri(["--foo", "str"], opts));
// => { _: [], foo: 'str' }

// ✅ cmd --foo "true"
console.log(mri(["--foo", "true"], opts));
// => { _: [], foo: 'true' }

// ✅ cmd --foo "false"
console.log(mri(["--foo", "false"], opts));
// => { _: [], foo: 'false' }

// ✅ cmd --no-foo
console.log(mri(["--no-foo"], opts));
// => { _: [], foo: false }

It's not documented that both boolean and string would work, but it seems to almost work as expected to me with the first case that should be true.

As a workaround, I'm doing something like this:

const args = process.argv.slice(2);
const parsed = mri(args, ...)

if (parsed.foo === "" && args[args.indexOf("--foo") + 1] !== "") {
  parsed.foo = true;
}

Related: changesets/changesets#1392