change graphql error handling with originalError

This commit is contained in:
Pierre Noël 2021-10-29 12:23:28 +02:00
parent d1b78ea881
commit ebb124de4b
3 changed files with 48 additions and 12 deletions

View File

@ -20,18 +20,17 @@ class ValidationError extends ApplicationError {
} }
} }
class YupValidationError extends ApplicationError { class YupValidationError extends ValidationError {
constructor(yupError, message) { constructor(yupError, message) {
super(); super();
const { errors, message: yupMessage } = formatYupErrors(yupError); const { errors, message: yupMessage } = formatYupErrors(yupError);
this.name = 'ValidationError';
this.message = message || yupMessage; this.message = message || yupMessage;
this.details = { errors }; this.details = { errors };
} }
} }
class PaginationError extends ApplicationError { class PaginationError extends ApplicationError {
constructor(message, details = {}) { constructor(message, details) {
super(message, details); super(message, details);
this.name = 'PaginationError'; this.name = 'PaginationError';
this.message = message || 'Invalid pagination'; this.message = message || 'Invalid pagination';

View File

@ -1,8 +1,44 @@
'use strict'; 'use strict';
const formatGraphqlError = error => { const { toUpper, snakeCase } = require('lodash/fp');
delete error.extensions.code; const {
HttpError,
ForbiddenError,
UnauthorizedError,
ApplicationError,
ValidationError,
} = require('@strapi/utils').errors;
const {
ApolloError,
UserInputError: ApolloUserInputError,
ForbiddenError: ApolloForbiddenError,
} = require('apollo-server-errors');
const formatToCode = name => `STRAPI_${toUpper(snakeCase(name))}`;
const formatGraphqlError = error => {
const originalError = error.originalError;
if (originalError instanceof ApolloError) {
return error;
}
if (originalError instanceof ForbiddenError || originalError instanceof UnauthorizedError) {
return new ApolloForbiddenError(originalError.message, { details: originalError.details });
}
if (originalError instanceof ValidationError) {
return new ApolloUserInputError(originalError.message, { details: originalError.details });
}
if (originalError instanceof ApplicationError || originalError instanceof HttpError) {
const name = formatToCode(originalError.name);
return new ApolloError(originalError.message, name, { details: originalError.details });
}
// Internal server error
strapi.log.error(error);
error.message = 'An error occured';
return error; return error;
}; };

View File

@ -3,6 +3,7 @@
const _ = require('lodash'); const _ = require('lodash');
const { prop, pick, reduce, map, keys, toPath, isNil } = require('lodash/fp'); const { prop, pick, reduce, map, keys, toPath, isNil } = require('lodash/fp');
const { contentTypes, parseMultipartData, sanitizeEntity } = require('@strapi/utils'); const { contentTypes, parseMultipartData, sanitizeEntity } = require('@strapi/utils');
const { ApplicationError, NotFoundError } = require('@strapi/utils').errors;
const { getService } = require('../utils'); const { getService } = require('../utils');
@ -94,7 +95,7 @@ const createLocalizationHandler = contentType => {
}; };
}; };
const createCreateLocalizationHandler = contentType => async (ctx = {}) => { const createCreateLocalizationHandler = contentType => async (args = {}) => {
const { copyNonLocalizedAttributes } = getService('content-types'); const { copyNonLocalizedAttributes } = getService('content-types');
const { sanitizeInput, sanitizeInputFiles } = createSanitizer(contentType); const { sanitizeInput, sanitizeInputFiles } = createSanitizer(contentType);
@ -103,28 +104,28 @@ const createCreateLocalizationHandler = contentType => async (ctx = {}) => {
? await strapi.query(contentType.uid).findOne({ populate: ['localizations'] }) ? await strapi.query(contentType.uid).findOne({ populate: ['localizations'] })
: await strapi : await strapi
.query(contentType.uid) .query(contentType.uid)
.findOne({ where: { id: ctx.id }, populate: ['localizations'] }); .findOne({ where: { id: args.id }, populate: ['localizations'] });
if (!entry) { if (!entry) {
return ctx.notFound('baseEntryId.invalid'); throw new NotFoundError();
} }
const { data, files } = ctx; const { data, files } = args;
const { findByCode } = getService('locales'); const { findByCode } = getService('locales');
if (isNil(data.locale)) { if (isNil(data.locale)) {
return ctx.badRequest('locale.missing'); throw new ApplicationError('locale is missing');
} }
const matchingLocale = await findByCode(data.locale); const matchingLocale = await findByCode(data.locale);
if (!matchingLocale) { if (!matchingLocale) {
return ctx.badRequest('locale.invalid'); throw new ApplicationError('locale is invalid');
} }
const usedLocales = getAllLocales(entry); const usedLocales = getAllLocales(entry);
if (usedLocales.includes(data.locale)) { if (usedLocales.includes(data.locale)) {
return ctx.badRequest('locale.already.used'); throw new ApplicationError('locale is already used');
} }
const sanitizedData = { const sanitizedData = {