UNPKG

@vtex/api

Version:
95 lines (94 loc) 4.07 kB
"use strict"; 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;