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

errorizer

v1.0.0

Published

A Express middleware for organizing and returning custom errors in JSON APIs

Downloads

6

Readme

errorizer

Travis Coveralls npm David license

An Express error middleware for organizing and returning custom errors in JSON APIs.

Without appending functions to Express objects, this package lets you:

  • return useful, standardized error responses to your clients;
  • declare API errors once, use them anywhere;
  • respond errors with ease, using only meaningful error codes;

Table of contents


Requirements

Usage

const express = require('express');
const errorizer = require('errorizer');

let app = express();

app.post('/users', (req, res, next) => {
  if (!isEmail(req.body.email)) {
    return next('INVALID_EMAIL');
  }
  if (emailExists(req.body.email)) {
    return next('EMAIL_ALREADY_EXISTS');
  }
  // ...
});

app.use(errorizer({
  INVALID_EMAIL: {
    status: 400,
    message: 'The email is not in a valid format'
  },
  EMAIL_ALREADY_EXISTS: {
    status: 400,
    message: 'The specified email already belongs to another user'
  }
}));

app.listen(3000);
// Response example

HTTP 400
Content-Type: "application/json; charset=utf-8"
{
  "status": "Bad Request",
  "code": "INVALID_EMAIL",
  "message": "The email is not in a valid format"
}

Defining errors

The API errors must be declared in an object and passed as a parameter to the main function.

let errors = { /* ... */ };
let errorMiddleware = errorizer(errors);
app.use(errorMiddleware);

The errors object must contain error codes as keys. The error codes will identify the error in your app and should also be used by clients.

As shown in the examples, each error may have these properties:

  • status (number, required): the HTTP status code for the error.
  • message (string, required): a brief description of the error.
  • detail (string/object/array, optional): a property for adding more details (e.g.: a longer description, a link to the documentation, etc.)

PROTIP: Declare your errors in a separate file (e.g.: errors.js) to keep your application startup file clean.

Example

// errors.js

module.exports = {

  INVALID_EMAIL: {
    status: 400,
    message: 'The email is not in a valid format'
  },

  EMAIL_ALREADY_EXISTS: {
    status: 400,
    message: 'The specified email already belongs to another user'
  },

  USER_NOT_FOUND: {
    status: 404,
    message: 'Could not find a user with the specified ID'
  },

  INVALID_LOGIN_OR_PASSWORD: {
    status: 401,
    message: 'The login and/or password are incorrect'
  }

};

Responding errors

When an error condition is met somewhere in the code, all that needs to be done is to make the error code reach Express' next function.

For convenience, you can specify the error code in multiple ways:

  • as a string;
  • within an instance of Error;
  • in the code property of an object

Example

errorizer({
  USER_NOT_FOUND: {
    status: 404,
    message: 'The specified user could not be found',
    detail: {
      description: 'This error occurs when the requested user does not exist',
      docs: 'http://docs.myapp.com/v1/errors/USER_NOT_FOUND'
    }
  }
});

// different ways to respond an error
function(req,res,next) => {
  // plain string
  next('USER_NOT_FOUND');

  // Error instance
  next(new Error('USER_NOT_FOUND'));

  // "code" property in object
  next({ code: 'USER_NOT_FOUND' });
}

// response sent for any of the above
HTTP 404
Content-Type: "application/json; charset=utf-8"
{
  "status": "Not Found",
  "code": "USER_NOT_FOUND",
  "message": "The specified user could not be found",
  "detail": {
    "description": "This error occurs when the requested user does not exist",
    "docs": "http://docs.myapp.com/v1/errors/USER_NOT_FOUND"
  }
}

Customizing errors with templates

Sometimes, you need an error response to contain values which may vary on every occurrence of it.

For example, a form validation response with information about all fields with invalid values for UI highlighting.

HTTP 400
Content-Type: "application/json; charset=utf-8"
{
  "status": "Bad Request",
  "code": "FORM_VALIDATION_ERROR",
  "message": "Some form fields contain invalid values",
  "detail": [
    {
      "field": "email",
      "message": "The email is required"
    },
    {
      "field": "password",
      "message": "The password is required"
    }
  ]
}

Or an error response containing data from the request.

HTTP 400
Content-Type: "application/json; charset=utf-8"
{
  "status": "Bad Request",
  "code": "INVALID_DATE",
  "message": "07/24/2017 is not a valid date",
  "detail": {
    "format": "YYYY-MM-dd",
    "docs": "http://docs.myapp.com/v1/errors/INVALID_DATE"
  }
}

You achieve this by declaring error templates and using the custom property!

Instead of declaring FORM_VALIDATION_ERROR and INVALID_DATE as static error objects, you can declare them as functions that return error objects (templates).

// errors.js

module.exports = {

  FORM_VALIDATION_ERROR: function(err) {
    return {
      status: 400,
      message: 'Some form fields contain invalid values',
      detail: err.custom
    }
  },

  INVALID_DATE: function(err) {
    return {
      status: 400,
      message: err.custom.date + ' is not a valid date',
      detail: {
        format: err.custom.format,
        docs: "http://docs.myapp.com/v1/errors/INVALID_DATE"
      }
    }
  }

};

Then, your route handlers can customize the errors by sending data in the custom property.

function(req, res, next) => {
  let formErrors = validateForm(req);
  if (formErrors.length > 0) {
    return next({
      code: 'FORM_VALIDATION_ERROR',
      custom: formErrors
    });
  }
};

function(req, res, next) => {
  const dateFormat = 'YYYY-mm-dd';
  if (!dateFormatIsCorrect(req.body.date, dateFormat)) {
    return next({
      code: 'INVALID_DATE',
      custom: {
        date: req.body.date,
        format: dateFormat
      }
    });
  }
};

Unexpected errors

If there's a bug in the code and an error is thrown out of nowhere, the error middleware will take care of it and generate the error below:

HTTP 500
Content-Type: "application/json; charset=utf-8"
{
  "status": "Internal Server Error",
  "code": "UNEXPECTED_ERROR",
  "message": "An unexpected error has occurred while fulfilling the request"
}

Contributing

Feel free to contribute. All feedback is welcome!

Before opening a pull request, make sure to have your changes covered by tests.

License

MIT