dthree / vorpal

Node's framework for interactive CLIs
http://vorpal.js.org
MIT License
5.64k stars 280 forks source link

Emit central error event from Vorpal #94

Open paglias opened 8 years ago

paglias commented 8 years ago

Would it be possible to have an event that catches all errors so we can respond accordingly?

For example every time I throw an error in command.validate() (fyi, it's not documented in the wiki) or command.action() I want to log the error somewhere and output a friendly error message.

dthree commented 8 years ago

Wouldn't you want to handle the error based on the context of the command?

I mean, I can have vorpal emit a global duplicate event of error, but I wouldn't want to suppress local errors.

Could you please explain a bit more? Thanks.

paglias commented 8 years ago

@dthree thanks for the quick response!

I'm used (in web apps) to have a global error handler and I think it would be useful for vorpal too:

command.action((args, callback) => {
  asyncOp(err => {
    // Do something with the error, maybe try to identify the cause, ...
   throw error; // error could be a specific error (NotFound()) or something more general
  })
};
vorpal.on('error', (error, context) {
   // Context would be similar to {command: commandName, args: actionArguments}
   // Print an error message and log the error in a separate file or maybe close the app...
})

This way you can have a central place where all error are handled so you can have a standardized handling and don't have to duplicate logic. This error handler should be passed the same context as the command that originated the error so that it could do things like this.log and access the command's args

paglias commented 8 years ago

You could do something similar by having an function to handle errors and call it like this:

command.action(async (args) => {
   // error happened
   return handleError(err, args, this);
})

but it would require to wrap all the code in try/catch code to correctly route errors to the specific handler

dthree commented 8 years ago

Okay I guess I'm okay with this:

vorpal.on('error', (error, context) {
   // Context would be similar to {command: commandName, args: actionArguments}
   // Print an error message and log the error in a separate file or maybe close the app...
})

BTW, when you programmatically execute Vorpal commands, this is already covered:

vorpal.exec('foo').then(function (data) {
  // didn't error
}).catch(function (err) {
  // errored
});

vorpal.exec('foo', function (err, data) {
  if (err) {

  }
});