strapi/packages/plugins/graphql/server/src/format-graphql-error.ts

73 lines
2.2 KiB
TypeScript
Raw Normal View History

import { toUpper, snakeCase, pick, isEmpty } from 'lodash/fp';
import { errors } from '@strapi/utils';
import { GraphQLError, type GraphQLFormattedError } from 'graphql';
const { HttpError, ForbiddenError, UnauthorizedError, ApplicationError, ValidationError } = errors;
const formatToCode = (name: string) => `STRAPI_${toUpper(snakeCase(name))}`;
const formatErrorToExtension = (error: any) => ({
error: pick(['name', 'message', 'details'])(error),
});
function createFormattedError(
formattedError: GraphQLFormattedError,
message: string,
code: string,
originalError: unknown
) {
const options = {
...formattedError,
extensions: {
...formattedError.extensions,
...formatErrorToExtension(originalError),
code,
},
};
return new GraphQLError(message, options);
}
/**
* The handler for Apollo Server v4's formatError config option
*
* Intercepts specific Strapi error types to send custom error response codes in the GraphQL response
*/
export function formatGraphqlError(formattedError: GraphQLFormattedError, originalError: unknown) {
// If this error doesn't have an associated originalError, it
2021-11-02 12:08:15 +01:00
if (isEmpty(originalError)) {
return formattedError;
}
const { message = '', name = 'UNKNOWN' } = originalError as Error;
if (originalError instanceof ForbiddenError || originalError instanceof UnauthorizedError) {
return createFormattedError(formattedError, message, 'FORBIDDEN', originalError);
}
if (originalError instanceof ValidationError) {
return createFormattedError(formattedError, message, 'BAD_USER_INPUT', originalError);
}
if (originalError instanceof ApplicationError || originalError instanceof HttpError) {
const errorName = formatToCode(name);
return createFormattedError(formattedError, message, errorName, originalError);
}
2021-10-27 18:54:58 +02:00
if (originalError instanceof GraphQLError) {
return formattedError;
2021-11-02 12:08:15 +01:00
}
// else if originalError doesn't appear to be from Strapi or GraphQL..
// Log the error
2021-11-02 12:08:15 +01:00
strapi.log.error(originalError);
// Create a generic 500 to send so we don't risk leaking any data
return createFormattedError(
new GraphQLError('Internal Server Error'),
'Internal Server Error',
'INTERNAL_SERVER_ERROR',
originalError
);
}