const {forEachField} = require('./utils'); const {maskErrors} = require('graphql-errors'); const errors = require('../errors'); const {Error: {ValidationError}} = require('mongoose'); // If an APIError happens in a mutation, then respond with `{errors: Array}` // according to the schema. const decorateWithMutationErrorHandler = (field) => { const fieldResolver = field.resolve; field.resolve = async (obj, args, ctx, info) => { try { return await fieldResolver(obj, args, ctx, info); } catch(err) { if (err instanceof errors.APIError) { return { errors: [err] }; } else if (err instanceof ValidationError) { // TODO: wrap this with one of our internal errors. throw err; } throw err; } }; }; /** * Masks errors during production and handle mutation errors inside the schema. * @param {GraphQLSchema} schema the schema to decorate * @return {void} */ const decorateWithErrorHandler = (schema) => { forEachField(schema, (field, typeName) => { // Handle mutation errors. if (typeName === 'RootMutation') { decorateWithMutationErrorHandler(field); } // If we are in production mode, don't show server errors to the front end. if (process.env.NODE_ENV === 'production') { // Mask errors that are thrown if we are in a production environment. maskErrors(field); } }); }; module.exports = { decorateWithErrorHandler, };