npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ryanmorr/blunder

v1.0.0

Published

A modern client-side JavaScript error handler

Downloads

63

Readme

blunder

Version Badge License Build Status

A modern client-side JavaScript error handler

Install

Download the CJS, ESM, UMD versions or install via NPM:

npm install @ryanmorr/blunder

Usage

Blunder offers the ability to normalize, enhance, capture, and report JavaScript errors in the browser:

import { monitor, subscribe, dispatch } from '@ryanmorr/blunder';

// Listen for global runtime errors
monitor();

// Subscribe to be notified when an exception is dispatched
subscribe((exception) => {
    // Log the exception to the server
    navigator.sendBeacon('/path/to/error/logger', JSON.stringify(exception));
});

// Manually dispatch an exception
dispatch('An error occurred!');

API

Exception(message?, options?)

Exception is a subclass of Error to help normalize and enhance error instances:

import { Exception } from '@ryanmorr/blunder';

// Create an exception just like a regular error
const exception = new Exception('error message');

// Normalizes the standard properties
exception.name;
exception.message;
exception.stack;

Add custom metadata as an optional second argument to help identify the error:

const exception = new Exception('error message', {
    timestamp: Date.now(),
    url: document.location.href,
    userAgent: navigator.userAgent
});

// The metadata is stored within the `data` property
exception.data.timestamp;
exception.data.url;
exception.data.userAgent;

Supports the cause property to facilitate error chaining:

try {
    connect();
} catch(error) {
    throw new Exception('Connection failed', {cause: error});
}

Extend Exception to create your own custom subclasses:

class APIException extends Exception {
    constructor(code, options){
        super('error code: ' + code, options);
        this.code = code;
    }
}

Includes a toJSON method that returns a key/value object representing all the properties of the exception. It will convert some non-JSON friendly values to friendly ones (such as functions) and will detect and avoid circular references:

function trySomething() {
    try {
        throw new Exception('error message', {source: trySomething});
    } catch(exception) {
        const serialized = exception.toJSON();
        serialized.data.source; //=> "[Function: trySomething]"
    }
}

You can override the serializable method in subclasses to customize how an instance is serialized:

class MyException extends Exception {
    serializable() {
        return `${this.name}: ${this.message}`;
    }
}

const exception = new MyException('An error occurred');
JSON.stringify(exception); //=> "MyException: An error occurred"

Exception also has a static from method that can be used to convert a value into an Exception instance:

// Supports error messages as strings
const exception = Exception.from('error message');

// Supports normal error instances (will copy standard properties)
const error = new Error();
const exception = Exception.from(error);

// Supports creating instances of subclasses
const exception = CustomException.from('error message');
exception instanceof CustomException; //=> true

subscribe(callback)

Subscribe a callback function to be invoked with an Exception instance when an error is dispatched, it returns an unsubscribe function:

import { subscribe } from '@ryanmorr/blunder';

const unsubscribe = subscribe((exception) => {
    // An exception was dispatched
});

// Unsubscribe from future error notifications
unsubscribe();

dispatch(error, options?)

Manually dispatch an Exception to the error subscribers and return the Exception instance:

import { dispatch } from '@ryanmorr/blunder';

// Supports strings
const exception = dispatch('error message');

// Supports normal error instances
dispatch(new Error());

// Supports custom metadata as an optional second argument
dispatch('error message', {foo: 1, bar: 2});

// Supports `cause` property
try {
    trySomething();
} catch(error) {
    dispatch('error message', {cause: error});
}

monitor(config?)

Enable global error monitoring by listening for the error, unhandledrejection, and rejectionhandled events. You can customize which events to listen for by providing a configuration object. It returns a function to disable monitoring:

import { monitor } from '@ryanmorr/blunder';

// Listen for all error events by default
const stop = monitor();

// Disable error monitoring
stop();

// Optionally specify which events to listen for
monitor({
    error: true,
    unhandledrejection: true,
    rejectionhandled: false
});

attempt(fn, options?)

Internally wraps a function in a try/catch block for easy error handling. If an error is raised, it is automatically converted to an Exception instance, dispatched to error subscribers, and then returned:

import { attempt } from '@ryanmorr/blunder';

const [result, exception] = attempt(() => {
    throw new Error();
});

// If `exception` is defined, the attempt failed
if (exception) {
    console.error(exception);
}

// If `result` is defined, the attempt was successful
if (result) {
    console.log(result);
}

Supports custom metadata as an optional second argument that will be added to the Exception instance if an error should arise:

const [result, exception] = attempt(callback, {
    viewportWidth: window.innerWidth,
    viewportHeight: window.innerHeight
});

Supports async functionality via promises by utilizing async/await syntax:

// Use promises directly
const [result, exception] = await attempt(fetch('/path/to/resource'));

// Use a function that returns a promise
const [result, exception] = await attempt(() => fetch('/path/to/resource'));

License

This project is dedicated to the public domain as described by the Unlicense.