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-err

v1.2.2

Published

Simplify error handling and logging for Node.

Downloads

250

Readme

node-err

Simplify error handling and logging for Node.

Index

Overview

One Error Handler

With node-err, you always use the same error handler, giving you expected behavior...

nodeErr.repeat(err);

const nodeErr = require('node-err');

return fetch()
  .catch(err => {
    return nodeErr.repeat(err);
  });

Bubbling-up Errors

With consistent error handling, bubbling-up errors is super easy...

return fetch()
  .catch(err => {
    return nodeErr.repeat(err);
  })
  .catch(err => {
    return nodeErr.repeat(err);
  })
  .catch(err => {
    return nodeErr.repeat(err);
  })
  .catch(err => {
    return next(err);
  });

Automatic logging

And logging/reporting is a breeze, it happens automatically...

nodeErr.repeat(err, details);

return fetchUsers()
  .catch(err => {

    let details = {
      name: 'FETCH_USERS',
      status: 500,
    };

    return nodeErr.repeat(err, details);
  });

Server Logging

Server logging happens out-of-the-box so you can set-up alerts with a service such as Papertrail...

papertrail -f SERVER_ERROR

fetch-error

Custom Logging

But you can set up your only logger too...

nodeErr.setup({ logger: myOwnLogger });

Custom Output Responses

Configure and send response data for outputting to the browser. View the Simple Promises example to see it in action.

nodeErr.setup({ responses: ['user_message','internal_code'] });

return saveAnalytics()
  .catch(err => {

    return nodeErr.repeat(err, {
      status: 500,
      responses: {
        user_message: 'Oops! Something went wrong.',
        internal_code: '2352',
      }
    });
  })
  .catch(err => {

    let statusCode = nodeErr.getStatus(err);
    let outputResponse = nodeErr.getResponse(err);
    
    return res.status(statusCode).send(outputResponse);
  });
}

Localized/Silent Error Handling

Sometimes you need to handle some errors a little differently, while still allowing other errors to bubble-up or pass through...

nodeErr.repeat(customVal)(err);

return saveAnalytics()
  .then(() => {

    // do more stuff with the ability to
    // bubble up a different fatal error

    return true;
  })
  .catch(err => {

    // if our saveAnalytics() failed, lets 
    // keep going and just return false

    return nodeErr.repeat(false)(err);
  })
  .then(result => {

    // did the analytics save ok?

    return (result) ? next() : retry();
  });
}

For more details, view the handling sections below.

Async/Await

(async function() {
  try {
    throw new Error('cubitum irem');
  } catch(err) {
    await nodeErr.repeat(err, { name: 'Do I know latin?' });
  }
})().catch(err => {
  // Hey Alexa...
});

Express Middleware

How about some Express middleware to catch/report any un-reported errors?

nodeErr.stop(err);

app.use((err, req, res, next) => {
  let details = { req };
  nodeErr.stop(err, details);
  return next(err);
});

Error Output

What should you do with all of these errors? Whatever you like...

app.use((err, req, res, next) => res.sendStatus( nodeErr.getStatus(err) ));

Technical

Getting Started

Just require node-err and start using repeat to automatically log and bubble-up errors...

const nodeErr = require('node-err');

return fetch()
  .catch(err => {
    return nodeErr.repeat(err);
  });

Config Vars (optional)

Call the setup function in your entry file (index.js or server.js) and pass config vars (optional)...

const nodeErr = require('node-err');

nodeErr.setup({
  prefix: 'FIND_THIS_ERROR',
  status: 401,
  debug: true,
  logger: (err) => slackChannel('Doh', err)),
  responses: ['user_message'],
  overrideResponses: true,
});

Key | Type | Description --- | --- | --- prefix | string | Global prefix added to all error logs. status | number | Default HTTP status code error. debug | bool | Output error repetition tracing. logger | func | Custom logging function (accepts Error obj). responses | array | Array of response properties. overrideResponses | bool | Allow automatic overwrite of responses when bubbling up.

Additional Error Details (optional)

When calling repeat add some more details so you know what went wrong (optional)...

nodeErr.repeat(err, {
  name: 'AWS_IMAGE_NOT_SAVED',
  req: req,
  status: 400,
  context: { imageName: 'budget-report.ppt'},
  responses: { user_message: 'Oops! Something went wrong.' },
  log: false,
  censor: true,
});

Key | Type | Description --- | --- | --- name | string | (optional) Custom error name. req | object | (optional) Express request object. status | bool | (optional) Desired http status response code. context | any | (optional) Whatever works. responses | object | (optional) Data to place on the response output. log | bool | (optional) Skip logging at this repeat node (intentional errors). censor | bool | (optional) Skip request body log (persists with bubbling up).

If req is provided, you'll also get access to:

  • IP Address
  • Requested URL
  • Request Body
  • Request Method
  • User Agent

Any responses data provided, must have its property added to the setup config.

Basic Block Error Handling/Bubbling

By default, calling repeat on an error the first time will create an error report and then reject it again with a Promise.reject.

Calling repeat again (in subsequent catch block) on an already reported error will just reject the same error again (no further reporting).

return fetch()
  .then(() => Promise.reject('level 1 error please'))
  .catch(err => {
    return nodeErr.repeat(err, { name: 'level 1' }); // report and rejects again
  })
  .then(() => doSomething()
  .catch(err => {
    return nodeErr.repeat(err, { name: 'level 2' }); // rejects level 1 error again
  })
  .then(() => doSomething()
  .catch(err => {
    return nodeErr.repeat(err, { name: 'level 3' }); // rejects level 1 error again
  })
  .catch(err => {
    return next(err); // returns level 1 error
  });

In this way, errors can bubble back up and be handled however you like.

Multi-directional Error Handling

You might want to handle some error differently, while still allowing processes above it to pass/bubble their errors through.

By using repeat with a custom value, which returns a callback and accepts, you can achieve multi-directional functionality:

  • Any previously reported will continue to bubble up and through.
  • Any un-reported errors will output with whatever value you set.

In this way, you can have a silent error handler for one process without breaking promise chain for processes above/before it.

nodeErr.repeat('It failed!')(err);

return saveAnalytics()
  .then(() => {
    return fetchUser();
  })
  .catch(err => {

    // if we didnt have a db conn error, and instead had an error
    // from saveAnalytics, the below would just return `false`

    return nodeErr.repeat(false)(err); // our db conn error will pass through
  })
  .then(result => {
    return (result) ? next() : retry(); // this is skipped because of our db conn error
  })
  .catch(err => {
    return next(err); // return db conn error
  })
}

function fetchUser() {

  return fetch()
    .then(result => {
      throw new Error('remote db conn err'); // fire error
    })
    .then(() => true) // this is skipped
    .catch(err => {
      return nodeErr.repeat(err, { name: 'FETCH_USER' }); // this will reject again
    })
}

You can also force an error report on a silent/custom error, so it will still show in the logs:

nodeErr.repeat('It failed!', true)(err);

Examples

Viewing the Examples

There are several examples included in the project. To run these...

  1. $ cd examples
  2. $ npm install
  3. $ npm run start
  4. Navigate to http://localhost:5000 for a directory of examples.