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

node-errors

v0.2.0

Published

Helper module for handling errors

Downloads

43

Readme

node-errors

Helper module for handling errors

Motivation

I like to translate system errors (such as filesystem errors or network errors) into custom errors with meaningful messages and also generate differents types of errors for different situations such as something was forbidden or something was not found. This way when developing an REST API it is easy for example to generate a good HTTP status code and response message.

Also I hate having to write if (err) all the time morover when I only need to translate the error and pass it through. Many times are errors difficult to test (e.g. a networking error) and if the body of that if finally happens to be run in production and it was not tested you can be screwed.

How it works

var errors = require('node-errors')

function findUser(id, callback) {
  db.query('SELECT * FROM users WHERE id=?', [id], function(err, results) {
    errors.with(callback)
      .on(err)
        .internal('Error while trying to find user with id = `%s`', id)
      .when(results.length === 0)
        .notFound('User not found with id = `%s`', id)
      .success(function() {
        callback(null, results[0])
      })
  })
}

A similar code without node-errors would be:

var errors = require('./custom-errors')
var InternalError = errors.InternalError
var NotFoundError = errors.NotFoundError

function findUser(id, callback) {
  db.query('SELECT * FROM users WHERE id=?', [id], function(err, results) {
    if (err) {
      return callback(new InternalError(err, 'Error while trying to find user with id = `%s`', id))
    } else if (results.length === 0) {
      return callback(new NotFoundError('User not found with id = `%s`', id))
    } else {
      return callback(null, results[0])
    }
  }
}

The amount of code is more or less the same but with node-errors you don't have to implement those custome errors, you can also create new custom errors easily (see below) and you will have 100% of test coverage easily and you don't need to be afraid of untested code. For instance: how do you test the case in which db.query returns an error? And thus, how do you test that the code inside that if won't crash your Node.js process?

Usage

You always start with errors.with(callback). That callback is the function that will be called in case of any error or unmet condition.

Then you use on(err) if you want to check against an existing error or when(condition) for any other condition, followed by a call to any of the following:

  • internal(message, [...]) For internal errors
  • forbidden(message, [...]) If there are not enough permissions to do something
  • request(message, [...]) For example when invalid parameters are passed in an HTTP request
  • notFound(message, [...]) When trying to read information of an unknown resource

Finally you will call success passing a callback function where you will put the code to be run when everything is ok.

You can check if an error has been generated by node-errors with errors.isCustomError(err). You can check for a specific error type with isXXX() (e.g. err.isInternal()) and you can also access the type field that will give you the error type in a string (internal, forbidden, request, notFound).

If a custom error was generated using on(err) then the custom error will have a root property defined referencing the initial error.

Custom errors

You can define custom errors easily. Just use errors.defineErrorType(type)

The following is a full example of how to define custom errors and how to use the

errors.defineErrorType('external')

function downloadPicture(id, callback) {
  http.downloadFile('.../'+id+'jpg', function(err, buffer) {
    errors.with(callback)
      .on(err)
        .external('There was an external error downloading picture with id = `%s`', id)
      .success(function() {
        callback(null, buffer)
      })
  })
}

downloadPicture('1234', function(err, buffer) {
  if (err) {
    errors.isCustomError(err) // true
    err.isExternal() // true
    err.type // 'external'
    err.root // the root error that generated this error
    return
  }
})

Creating custom errors directly

You can also create custom errors directly. Example:

var err = errors.notFound('User not found `%s`', email)

If the last argument is an error object it is not used to format the error message and it is set to the err.root field.

var err = errors.internal('Internal error', error)
err.root === error // true

Listening to errors

Another thing you can do is to easily listen to errors. The node-errors module is an EventEmitter that emits events when errors are generated. So you can do:

errors.on('internal', function(err) {
  // log this internal error
})

You could for example generate a custom critical error type and everytime that one critical error is generated you could send an SMS to somebody. For example if a payment gateway fails, or whatever.

Using the utility nook function

I find myself writing many times code like this:

somethingAsync(function(err, arg) {
  if (err) return callback(err)
  callback(null, arg+something)
})

If you don't want to translate any error, just pass it through you can use the nook function:

var nook = errors.nook

somethingAsync(nook(callback,
  function(arg) {
    callback(null, arg+something)
  })
)

And if you just want to pass an already known argument or arguments in case of success you can do:

somethingAsync(nook(callback, something))

In case of error the callback function will be called with that error. In case of success the callback function will be called with callback(null, something)