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

@guilhermemj/app-error

v1.1.0

Published

Error subclass on steroids for custom application exceptions

Downloads

5

Readme

App Error

Make application errors easier to handle

Installation

npm install @guilhermemj/app-error

Usage

Simply throw an AppError like you would with any normal Error. You can, however, pass a second argument with some options to customize error context and meta info.

var AppError = require("@guilhermemj/app-error");

// Basic usage
throw new AppError("Ops, something went wrong!");

throw new AppError("Resource not found!", {
  httpStatusCode: 404,
  code: "ERR_NOT_FOUND",
});

// Full customization
throw new AppError("Resource version differs from database", {
  httpStatusCode: 409,
  code: "ERR_RESOURCE_CONFLICT",
  level: "warn",
  meta: {
    user: "@johndoe",
    resourceId: "123456",
    informedData: {/* ... */},
    expectedData: {/* ... */},
  },
});

Where AppError really shines is when catching and handling thrown errors. Besides the mentioned options, each error has an unique id and date object making it very easy to log errors and normalize API responses.

Here, we simulate an express controller response with a totally arbitrary logger function to show the difference between handling an AppError and other common errors:

var AppError = require("@guilhermemj/app-error");

try {
  // Do some code...
} catch (error) {
  if (error instanceof AppError) {
    logger[error.level](error.message, error.code, {
      // `meta` may have important info about error context
      meta: error.meta,
      date: error.date,
      uuid: error.id,
    });

    res.status(error.httpStatusCode).json({
      message: error.message,
      code: error.code,
      uuid: error.id,
    });
  } else {
    // Something REALLY bad happened! But we only have a message to log :(
    logger.error(error.message, "ERR_INTERNAL_ERROR", { date: new Date() });

    res.status(500).json({
      message: error.message,
      code: "ERR_INTERNAL_ERROR",
    });
  }
}

Please note how we are able to log much richier information with AppError and how easy it is to identify it's instances.

Presets

In order to improve code DRYness it's recommended to create some presets for common errors in your application. Typescript users have the AppErrorOptions interface available for this purpose.

To avoid destructuring and other workarounds when using presets, AppError constructor accepts a third parameter to be used as the meta object option.

import AppError, { AppErrorOptions } from "@guilhermemj/app-error";

const ERR_INVALID_CONFIG: AppErrorOptions = {
  httpStatusCode: 400,
  code: "ERR_INVALID_CONFIG",
  level: "debug",
};

if (!isValidEmail(payload.email)) {
  throw new AppError(`"${payload.email}" is not a valid email`, ERR_INVALID_CONFIG, { payload, invalidField: "email" });
}

if (!payload.password) {
  throw new AppError("Password is required", ERR_INVALID_CONFIG, { payload, invalidField: "password" });
}

Options

httpStatusCode

  • Type: number
  • Default: 500

Status code to be used on API responses. (List of existing codes)

code

  • Type: string
  • Default: "ERR_UNCAUGHT_EXCEPTION"

Error code. Can be used to identify errors of the same type.

level

  • Type: "error" | "warn" | "info" | "debug"
  • Default: "error"

Error severity level. Useful for logging.

meta

  • Type: Object
  • Default: {}

Extra info about the error to be retrieved later.

It's very common to enrich logs and API responses with some execution context. This is where you should store it.