Git Product home page Git Product logo

graphql-apollo-errors's Introduction

graphql-apollo-errors

A small library to handle graphql and apollo errors in a better way

This library is fully tested with 100% coverage

CircleCI Coverage Status Donate

Initiative

Error handling requires few core features to be useful:

  • Ability to customize error in well defined structure cross app
  • Ability to hook the error bubbling (In order to log or store the errors somewhere)
  • Ability to send the error to the client while sending all the relevant information yet keeping all the sensitive information only on the server

Looking around I found only 2 libraries dealing with errors in graphql and apollo - graphql-errors , apollo-errors.

Both libraries are great start, but they are not powerful enough for my opinion, therefore I decided to write my own error handler. Talking with some friends, I understand I'm not alone with this need, so I created this library as open source.

Usage

(Look in the spec files to understand more)

Configure apollo error formatting

import express from 'express';
import bodyParser from 'body-parser';
import { formatErrorGenerator } from 'graphql-apollo-errors';
import schema from './schema';
// You can use what ever you want, this is just an example
var logger = require('minilog')('errors-logger');

const formatErrorOptions = {
  logger,
  publicDataPath: 'public', // Only data under this path in the data object will be sent to the client (path parts should be separated by . - some.public.path)
  showLocations: true, // whether to add the graphql locations to the final error (default false)
  showPath: true, // whether to add the graphql path to the final error (default false)
  hideSensitiveData: false, // whether to remove the data object from internal server errors (default true)
  hooks: {
    // This run on the error you really throw from your code (not the graphql error - it means not with path and locations)
    onOriginalError: (originalError) => {logger.info(originalError.message)},
    // This will run on the processed error, which means after we convert it to boom error if needed
    // and after we added the path and location (if requested)
    // If the error is not a boom error, this error won't include the original message but general internal server error message
    // This will run before we take only the payload and the public path of data
    onProcessedError: (processedError) => {logger.info(processedError.message)},
    // This will run on the final error, it will only contains the output.payload, and if you configured the publicDataPath
    // it will only contain this data under the data object
    // If the error is internal error this error will be a wrapped internal error which not contains the sensitive details
    // This is the error which will be sent to the client
    onFinalError: (finalError) => {logger.info(finalError.message)},
  },
  nonBoomTransformer: (nonBoomError) => {error instanceof GraphQLError ? SevenBoom.badRequest(error.message) : SevenBoom.badImplementation(error)}
  // Optional function to transform non-Boom errors, such as those from Apollo & other 3rd-party libraries, into Boom errors
};
const formatError = formatErrorGenerator(formatErrorOptions);
const app = express();

app.use('/graphql',
  bodyParser.json(),
  graphqlExpress({
    formatError,
    schema
  })
);

app.listen(8080)

Init SevenBoom object The defalut args for SevenBoom are

const defaultArgsDef = [
  {
    name : 'errorCode',
    order: 1
  }, {
    name : 'timeThrown',
    order: 2,
    default: null
  }, {
    name : 'guid',
    order: 3,
    default: null
  }
];

If you want you can change it using the initSevenBoom function:

import { initSevenBoom } from 'graphql-apollo-errors';
const customArgsDefs = [
  {
    name : 'errorCode',
    order: 1
  }
];
initSevenBoom(customArgsDefs);

Use SevenBoom to create your custom error and throw it.

import { SevenBoom } from 'graphql-apollo-errors';

// A resolver which throws error
const getUserByIdResolver = (root, { userId }, context) => {
  UserService.getUserById(userId)
  .then((user) => {
    if (user) return user;
    const errorMessage = `User with id: ${userId} not found`;
    const errorData = { userId };
    const errorName = 'USER_NOT_FOUND';
    const err = SevenBoom.notFound(errorMessage, errorData, errorName);
    throw(err);
  }
}

Enjoy your shiny error on the client

{
  "data": {},
  "errors": [
    {
      statusCode: 404,
      error: 'Not Found',
      message: 'User with id: 123 not found.',
      code: 'USER_NOT_FOUND',
      timeThrown: "2017-01-16T21:25:58.536Z",
      guid: 'b6c44655-0aae-486a-8d28-533db6c6c343',
      data: {
        userId: '123'
      }
    }
  ]
}

Upgrade from v1..

There is a lot of changes from v1. (In the implementation, which leads to API changes)

  • onStoredError hook is no longer exist (actually the onOriginalError result is the same as the onStoredError before)
  • You should not use the throwError any more (it was deleted), you can use the native throw now.

How does it work

In general this library contain 2 parts:

  1. SevenBoom - A small library i wrote to create customize errors
  2. format error function - which knows to fetch the real error, hide sensitive server data, add some hooks points and configuration, and pass it to the client.

License

MIT - Do what ever you want

Contribute

I'm open to hear any feedback - new ideas, bugs, needs. Feel free to open issues / PR

Support on PayPal

Hey dude! Help me out for a couple of ๐Ÿป!

Donate

graphql-apollo-errors's People

Contributors

alminde7 avatar giladshoham avatar keithgillette avatar kievechua avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

graphql-apollo-errors's Issues

Parameters of methods' SevenBoom no function correctly

The next code not function correctly, specifically the parameter errorData to several methods

//Code take of your example

import { SevenBoom } from 'graphql-apollo-errors';

// A resolver which throws error

const getUserByIdResolver = (root, { userId }, context) => {
  UserService.getUserById(userId)
  .then((user) => {
    if (user) return user;
    const errorMessage = `User with id: ${userId} not found`;
    const errorData = { userId };
    const errorName = 'USER_NOT_FOUND';
    const err = SevenBoom.notFound(errorMessage, errorData, errorName);
    throw(err);
  }
}

Example

Awesome package !

Is it possible to get a working example, because I set up all the config from the README, and I still have an error on the browser like this:

screen shot 2017-03-03 at 17 54 06

Feature Request: White-list non-Boom errors / Pass-through GraphQL errors / Override `internal server error`

I have found graphql-apollo-errors very useful to simplify error handling in our Apollo-based project. Thanks for publishing this package!

One shortcoming I've run into is the inability to get error messages from Apollo itself (such as cannot query field and similar for malformed operations) or error messages from third-party queries and mutations loaded via graphql-loader. I certainly understand that you want to prevent exposing general uncaught application exceptions, but providing some mechanism for allowing non-Boom errors to pass-through would be extremely useful.

Perhaps the simplest and most dangerous option would be to just include a formatErrorGenerator configuration flag to override the default behavior and allow non-Boom errors to pass-through. If there's an easy way to know whether the error is coming from Apollo itself or from a graphql-loader originated operation, then I'd think it would be safe to just pass those through, as well. Otherwise, providing a function hook to white-list errors would be another option.

Error in formatError function

I am getting Error in formatError function: TypeError: Cannot read property 'output' of undefined. followed the instructions setting up it with Apollo.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.