buggin
v0.1.7
Published
help your users report unexpected errors originating in your buggy app
Downloads
5
Maintainers
Readme
buggin
help users report errors from your buggy app :grimacing:
What buggin
Is
buggin
will intercept uncaught exceptions (and unhandled rejections) from your app, and ask the user to create a bug report. It looks something like this (customizable):
The new issue will be pre-filled with the exception and other info. Neat!
What buggin
Ain't
buggin
will not attempt to determine whether or not the exception was thrown from your code.
Exceptions which originate in your package's dependencies may be because of misuse ("user error" on your part) or an actual bug in the dependency--there's really no way to tell. Either way, such a bug should be reported, so a maintainer of a package using buggin
can triage and determine if it's an "upstream" problem or not.
Install
Currently, buggin
only works with repos hosted on GitHub.
The usual:
npm i buggin
Usage
Basic Usage
You only need to call buggin()
once. You should do this in your CLI app entry point (the script in your bin
prop of package.json
).
#!/usr/bin/env node
// your other requires go here
require('buggin')(module);
// start doing stuff with args
Advanced Usage
Custom Messaging
To override the default message, create a BugginMessageBuilder
function which accepts a BugginMessageBuilderData
object and returns a string
. Pass this to buggin
's options object via property builder
.
Example:
require('buggin')(module, {
builder: ({
/**
* - `true` if error came from a unhandled rejection
* @type {boolean}
*/
isPromise,
/**
* - Project name
* @type {string}
*/
projectName,
/**
* - New issue URL
* @type {string}
*/
url,
/**
* - Original error
* @type {Error}
*/
error,
/**
* - `true` if the terminal supports color
* @type {boolean}
*/
supportsColor
}) => {
return `my custom message. please make a new issue here: ${url}`;
});
Note that the error message and stack trace is always displayed after buggin
's output. The idea is that you could use it to conditionally change the message output (if needed).
If you want colors or emoji, you're on your own; buggin
uses ansi-colors and node-emoji internally.
Emoji and colors are automatically stripped if the terminal lacks support. Or...that's the idea, anyway. Colors for sure.
Use With Existing Process Event Listeners
If your module (or some module you're consuming) listens on Process.uncaughtException or Process.unhandledRejection, buggin
will refuse to set up its own listeners, print a message to STDERR
with a warning, and exit the process.
If you'd still like to try it, pass force: true
to the options argument:
buggin(module, {force: true});
Because your own listeners could do literally anything and buggin
can't know what it is they are doing, you'll just have to try it.
Manual Configuration
The auto-configuration behavior can be overridden by a few other options:
// custom package name
buggin(module, {name: 'custom name'});
// custom package json with custom entryPoint (for stack sniffing)
buggin(require('/path/to/package.json'), {entryPoint: '/my/package/root/'});
// path to package.json
buggin('/path/to/package.json');
Ignoring Certain Errors
You can pass buggin
a selector function to help it determine whether an Error
should be ignored by buggin
.
This is helpful if a certain class of Error
s are known or expected. For example, if you expect your app to throw an Error
with a code property of EISDIR
, you can use the following code, and buggin
will not intercept the exception:
buggin(module, {reject: err => err.code === 'EISDIR'});
Editor's Note: It's probably a better idea to actually catch these exceptions so they don't become uncaught, right?
Because of the nature of the problem--we're trying to get bug reports for unexpected errors--buggin
does not support an "accept" selector function, would return true
if the Error
was to be handled by buggin
. To write such a function, you'd need to know something about the errors you want buggin
handle, and in so, defeating the purpose.
How It Works
buggin
does what it thinks is correct, but its understanding of what "correct" means is up for further discussion.
Interception of Uncaught Exceptions & Unhandled Rejections
buggin
prepends a listener to both the Process.uncaughtException and Process.unhandledRejection events. If one of these events is emitted with an Error
argument, buggin
will:
- Print a notification to
STDERR
and a link to the "new issue" page. If the user's terminal supports it, the URL will be displayed as a clickable link, with the requisite querystring hidden; otherwise the entire URL (with query string) will be displayed for the user to copy/paste. buggin
disables all of its listeners (including this one).buggin
makes a choice:- If there's no other listener which was not added by
buggin
for the emitted event, the error...- ...if an uncaught exception, will be rethrown on the next tick out of
buggin
's listener. - ...if an unhandled rejection, will be re-rejected from the handler.
- ...if an uncaught exception, will be rethrown on the next tick out of
- In both above "pass through" situations,
buggin
attempts to mimic the default behavior as closely as possible. It will suppress the callsite of its rethrow/rejection, which is unhelpful because ti will point to code inbuggin
. There may be a way to save this info from the original error? - If there is another listener,
buggin
will not rethrow (nor re-reject), and will continue to the next listener as per standard Node.js EE behavior.
- If there's no other listener which was not added by
Auto-Configuration
buggin
attempts to automatically determine the package name and the URL from your package's package.json
. The logic is kind of gross, but by default, it looks for closest package.json
to the main (entry) script, and pulls the info out.
Motivation
This is the opposite of "This is probably not a problem with npm." The fact is, if someone is running your CLI app (and you aren't invoking someone else's code), it is your problem. Wouldn't you like to fix it?
Most users don't bother to report bugs, so maybe this will help!
Caveats
- This module is intended for use with CLI apps. That said, if you have an idea for better library support, propose something!
- Only a single package can use
buggin
at once. If the "main" module usesbuggin
, it will be preferred over all others; any attempts to usebuggin
after (or before!) the "main" module does will be ignored. If the consumer is not the main module, then only the most recent package to callbuggin
"wins." - Under normal circumstances, Node.js will exit with code 7 if an uncaught exception is handled and rethrown from the listener. Because
buggin
does not rethrow out of the listener per se--and instead rethrows on "next tick"--the process will exit with code 1 (as if no such handling occurred). - Behavior on unhandled rejection depends on the version of Node.js used. Node.js v12 added a
--unhandled-rejections-mode
option, which allows for greater control over whether an unhandled rejection is considered a "warning" or a nonzero-exit-code-producing error. buggin
ignores non-Error
exceptions or rejections.buggin
throws stuff in theglobal
context (a singleton prop calledbuggin
which stores its configuration) to deal with multiple usages more gracefully. Deal with it!
TODO
- Custom output template
- Custom issue template (can we reference an existing GitHub issue template?)
License
Licensed Apache-2.0