@vtex/api
Version:
VTEX I/O API client
95 lines (94 loc) • 4.07 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.graphqlError = void 0;
const apollo_server_errors_1 = require("apollo-server-errors");
const ramda_1 = require("ramda");
const constants_1 = require("../../../../../constants");
const RequestCancelledError_1 = require("../../../../../errors/RequestCancelledError");
const logger_1 = require("../../../../logger");
const error_1 = require("../utils/error");
const pathname_1 = require("../utils/pathname");
const TWO_SECONDS_S = 2;
const uniqErrorsByPath = (errors) => (0, ramda_1.uniqBy)(e => e.extensions && e.extensions.exception && e.extensions.exception.request
? e.extensions.exception.request.path
: e, errors);
const createLogErrorToSplunk = (vtex) => (err) => {
var _a, _b, _c, _d, _e, _f;
const { route: { id }, logger, } = vtex;
try {
// Prevent logging cancellation error (it's not an error)
if (((_b = (_a = err === null || err === void 0 ? void 0 : err.extensions) === null || _a === void 0 ? void 0 : _a.exception) === null || _b === void 0 ? void 0 : _b.code) === RequestCancelledError_1.cancelledErrorCode) {
return;
}
// Add pathName to each error
if (err.path) {
err.pathName = (0, pathname_1.generatePathName)(err.path);
}
const log = {
...err,
routeId: id,
};
// Grab level from originalError, default to "error" level.
let level = (_d = (_c = err === null || err === void 0 ? void 0 : err.extensions) === null || _c === void 0 ? void 0 : _c.exception) === null || _d === void 0 ? void 0 : _d.level;
if (!level || !(level === logger_1.LogLevel.Error || level === logger_1.LogLevel.Warn)) {
level = logger_1.LogLevel.Error;
}
logger.log(log, level);
}
finally {
if (!constants_1.LINKED && ((_f = (_e = err === null || err === void 0 ? void 0 : err.extensions) === null || _e === void 0 ? void 0 : _e.exception) === null || _f === void 0 ? void 0 : _f.sensitive)) {
delete err.extensions.exception.sensitive;
}
}
};
async function graphqlError(ctx, next) {
const { vtex: { production }, } = ctx;
let graphQLErrors = null;
try {
await next();
const response = ctx.graphql.graphqlResponse;
if (response && Array.isArray(response.errors)) {
const formatter = (0, error_1.createFormatError)(ctx);
graphQLErrors = (0, apollo_server_errors_1.formatApolloErrors)(response.errors, { formatter });
}
}
catch (e) {
if (e.code === RequestCancelledError_1.cancelledErrorCode) {
ctx.status = RequestCancelledError_1.cancelledRequestStatus;
return;
}
const formatError = (0, error_1.createFormatError)(ctx);
graphQLErrors = Array.isArray(e)
? e.map(formatError)
: [formatError(e)];
// Add response
ctx.status = e.statusCode || 500;
if (e.headers) {
ctx.set(e.headers);
}
}
finally {
if (graphQLErrors) {
ctx.graphql.status = 'error';
// Filter errors from the same path in the query. This should
// avoid logging multiple errors from an array for example
const uniqueErrors = uniqErrorsByPath(graphQLErrors);
// Log each error to splunk individually
const logToSplunk = createLogErrorToSplunk(ctx.vtex);
uniqueErrors.forEach(logToSplunk);
// In production errors, add two second cache
if (production) {
ctx.graphql.cacheControl.maxAge = TWO_SECONDS_S;
}
else {
ctx.graphql.cacheControl.noCache = true;
ctx.graphql.cacheControl.noStore = true;
}
ctx.graphql.graphqlResponse = {
...ctx.graphql.graphqlResponse,
errors: uniqueErrors,
};
}
}
}
exports.graphqlError = graphqlError;