tj/commander.js

Usage with Bun

Closed this issue · 5 comments

I'm trying to build a CLI in TS with Bun, but the issue that the behavior is different from bun ./src/cli.ts command and node ./dist/cli.js command,

I'm getting this error from commander when using bun:
image

for some reasons, commander is trying to merge the name with the command and then try to evaluate it, for instance if I provide pizza to the new Command('pizza'), the error became
image

it only works when I try to do something like bun run ./src/cli.ts {name}-release while changing the name to the name passed to new Command(name)

My code:

const prog = new Command(pkg.name);

prog.description(pkg.description).version(pkg.version);

prog
  .command('release', 'Run the fluid release tool to create a release')
  .option(releaseOptions.immediate.flags, releaseOptions.immediate.desc, releaseOptions.immediate.default)
  .option(releaseOptions.base.flags, releaseOptions.base.desc, releaseOptions.base.default)
  .option(releaseOptions.head.flags, releaseOptions.head.desc, releaseOptions.head.default)
  .option(releaseOptions.count.flags, releaseOptions.count.desc, Number, releaseOptions.count.default)
  .action(async (opts: ReleaseCommandOptions) => release(await getReleaseOptions(opts)));


prog.parse();

Move the command description into a separate method like:

prog
   .command('release')
   .description('Run the fluid release tool to create a release')

(For historical reasons, the signature with command name and description together as parameters triggers a different model where the command is implemented as an external command named like ${programName}-${commandName}.)

Move the command description into a separate method like:

prog
   .command('release')
   .description('Run the fluid release tool to create a release')

(For historical reasons, the signature with command name and description together as parameters triggers a different model where the command is implemented as an external command named like ${programName}-${commandName}.)

It worked!

but I think it would be helpful to be documented

but I think it would be helpful to be documented

This is covered in the README, but is still subtle.

I noticed when running with node that you get extra clues when the (accidental) external command is not found. The error handling is a little different in Bun and this helpful extra text did not get displayed. I'll have a look at whether this can be displayed when using Bun too.

% node cli.js release 
/Users/john/Documents/Sandpits/commander/my-fork/lib/command.js:1225
        throw new Error(executableMissing);
        ^

Error: 'super-release' does not exist
 - if 'release' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
 - if the default executable name is not suitable, use the executableFile option to supply a custom name or path
 - searched for local subcommand relative to directory '/Users/john/Documents/Sandpits/commander/issues/2195'
    at ChildProcess.<anonymous> (/Users/john/Documents/Sandpits/commander/my-fork/lib/command.js:1225:15)
    at ChildProcess.emit (node:events:519:28)
    at ChildProcess._handle.onexit (node:internal/child_process:292:12)
    at onErrorNT (node:internal/child_process:484:16)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)

Node.js v20.13.0

I think bun might be throwing an exception from the spawn call while node is sending an error event. Looks hard enough to improve that I'll wait and see if other Bun users hit same problem.

proc = childProcess.spawn(executableFile, args, { stdio: 'inherit' });