buggin
TypeScript icon, indicating that this package has built-in type declarations

0.1.7 • Public • Published

buggin logo buggin

help users report errors from your buggy app 😬

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):

screenshot of output

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 Errors 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:

  1. 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.
  2. buggin disables all of its listeners (including this one).
  3. buggin makes a choice:
    1. If there's no other listener which was not added by buggin for the emitted event, the error...
      1. ...if an uncaught exception, will be rethrown on the next tick out of buggin's listener.
      2. ...if an unhandled rejection, will be re-rejected from the handler.
    2. 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 in buggin. There may be a way to save this info from the original error?
    3. 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.

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 uses buggin, it will be preferred over all others; any attempts to use buggin 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 call buggin "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 the global context (a singleton prop called buggin 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

Package Sidebar

Install

npm i buggin

Weekly Downloads

1

Version

0.1.7

License

Apache-2.0

Unpacked Size

110 kB

Total Files

10

Last publish

Collaborators

  • boneskull