@sap/cds-dk
Version:
Command line client and development toolkit for the SAP Cloud Application Programming Model
119 lines (100 loc) • 4.27 kB
JavaScript
module.exports = {
pruneErrors
};
let interceptor
function pruneErrors() {
if (interceptor) {
// Already set up.
return;
}
interceptor = true;
function stacklessError(message) {
const { stackTraceLimit } = Error;
Error.stackTraceLimit = 0;
const error = new Error(message);
Error.stackTraceLimit = stackTraceLimit;
return error;
}
require('axios').interceptors.response.use(
response => response,
axError => {
const { inspect } = require('util');
let { url, method } = axError.config ?? {};
url = url?.replace(/(passcode|refreshToken|clientsecret|key)=[^&]+/g, '$1=...');
const { errno, code, response = {}, message: axMessage } = axError;
const prefix = (url && method ? `${method.toUpperCase()} ${url}` : 'Request') + ' failed';
function fixData(data) {
if (Buffer.isBuffer(data)) {
let str = data.toString();
try {
data = JSON.parse(str);
} catch {
data = str;
}
}
return data;
}
function extractErrorDetails(data) {
if (!data) return undefined;
if (typeof data === "string") {
if (/<html/i.test(data)) {
return '(HTML response received. If applicable, ensure the route to MTX is configured correctly in App Router.)';
}
if (data.length >= 1000) return undefined;
return data.trim();
}
if (typeof data === "object") {
if (data.error_description) return data.error_description; // OAuth RFC
if (data.error && typeof data.error === "object" && data.error.message) return data.error.message;
if (data.error && typeof data.error === "string") return data.error;
if (typeof data.message === "string") return data.message;
return inspect(data); // fallback
}
return undefined;
}
let error;
const debug = require('../').log('req')._debug;
if (errno) {
// System/network errors
const message = prefix +
`: ${errno} ${code}` +
(/\b(ENOTFOUND|EAI_AGAIN)\b/.test(code)
? `. Make sure the URL is correct and the server is running.`
: '');
error = stacklessError(message);
} else {
// HTTP errors
const { status, statusText } = response;
let { data } = response;
data = fixData(data);
const details = extractErrorDetails(data);
const reason = typeof data?.error === "string"
? data.error
: undefined;
const errObj = debug && typeof data.error === 'object'
? inspect(data.error)
: undefined;
const message = prefix +
(status || statusText || reason || details
? (status || statusText ? ':' : '') +
(status ? ` ${status}` : '') +
(statusText ? ` ${statusText}` : '') +
(reason ? `. ${reason}` : '') +
(details ? `. Details: ${details}` : '') +
(errObj ? `. Error object: ${errObj}` : '')
: (axMessage ? `: ${axMessage}` : '')
);
error = stacklessError(message);
if (status) error.status = status;
if (data?.passcode_url) {
error.auth = { passcode_url: data.passcode_url };
}
}
if (debug) {
error.cause = axError;
}
return Promise.reject(error);
}
);
return module.exports;
}