@vepler/http-client
Version:
A flexible and extensible API service library for making HTTP requests with built-in authentication support for bearer tokens and API keys.
199 lines • 7.51 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseAxiosError = exports.sanitizeResponse = exports.sanitizeConfig = exports.truncateData = exports.sanitizeHeaders = void 0;
/**
* Sensitive field patterns that should be redacted from logs
*/
var SENSITIVE_FIELDS = [
/key/i,
/token/i,
/secret/i,
/password/i,
/auth/i,
/credential/i,
/session/i,
/jwt/i,
/signature/i,
/private/i,
];
/**
* Safe replacement for sensitive data
*/
var REDACTED = '[REDACTED]';
/**
* Maximum size for data objects in error logs to prevent excessive memory usage
*/
var MAX_ERROR_SIZE = {
STRING: 1000,
ARRAY: 50,
OBJECT: 20, // properties
};
/**
* Clean sensitive data from headers
*/
function sanitizeHeaders(headers) {
if (headers === void 0) { headers = {}; }
var sanitized = {};
Object.entries(headers).forEach(function (_a) {
var key = _a[0], value = _a[1];
if (SENSITIVE_FIELDS.some(function (pattern) { return pattern.test(key); })) {
if (typeof value === 'string' && value.length > 8) {
// Mask but show first and last 4 chars of long strings
sanitized[key] = "".concat(value.substring(0, 4), "...").concat(value.substring(value.length - 4));
}
else {
sanitized[key] = REDACTED;
}
}
else {
sanitized[key] = value;
}
});
return sanitized;
}
exports.sanitizeHeaders = sanitizeHeaders;
/**
* Truncate strings, arrays and objects to prevent excessive logging
*/
function truncateData(data, depth) {
if (depth === void 0) { depth = 0; }
if (depth > 3) {
return '[Nested Object]';
}
if (data === null || data === undefined) {
return data;
}
if (typeof data === 'string') {
if (data.length > MAX_ERROR_SIZE.STRING) {
return "".concat(data.substring(0, MAX_ERROR_SIZE.STRING), "... [truncated ").concat(data.length - MAX_ERROR_SIZE.STRING, " chars]");
}
return data;
}
if (typeof data === 'object') {
if (Array.isArray(data)) {
if (data.length > MAX_ERROR_SIZE.ARRAY) {
return __spreadArray(__spreadArray([], data.slice(0, MAX_ERROR_SIZE.ARRAY).map(function (item) { return truncateData(item, depth + 1); }), true), ["[...".concat(data.length - MAX_ERROR_SIZE.ARRAY, " more items]")], false);
}
return data.map(function (item) { return truncateData(item, depth + 1); });
}
var entries = Object.entries(data);
if (entries.length > MAX_ERROR_SIZE.OBJECT) {
var truncated_1 = {};
entries.slice(0, MAX_ERROR_SIZE.OBJECT).forEach(function (_a) {
var key = _a[0], value = _a[1];
truncated_1[key] = truncateData(value, depth + 1);
});
truncated_1['[truncated]'] = "".concat(entries.length - MAX_ERROR_SIZE.OBJECT, " more properties");
return truncated_1;
}
var sanitized_1 = {};
entries.forEach(function (_a) {
var key = _a[0], value = _a[1];
if (SENSITIVE_FIELDS.some(function (pattern) { return pattern.test(key); })) {
sanitized_1[key] = REDACTED;
}
else {
sanitized_1[key] = truncateData(value, depth + 1);
}
});
return sanitized_1;
}
return data;
}
exports.truncateData = truncateData;
/**
* Clean an Axios config object for safe logging
*/
function sanitizeConfig(config) {
if (config === void 0) { config = {}; }
var headers = config.headers, auth = config.auth, params = config.params, data = config.data, rest = __rest(config, ["headers", "auth", "params", "data"]);
return __assign(__assign({}, rest), { headers: headers ? sanitizeHeaders(headers) : undefined, auth: auth ? { username: auth.username, password: REDACTED } : undefined, params: params ? truncateData(params) : undefined, data: data ? truncateData(data) : undefined });
}
exports.sanitizeConfig = sanitizeConfig;
/**
* Clean an Axios response object for safe logging
*/
function sanitizeResponse(response) {
if (!response)
return null;
var data = response.data, headers = response.headers, config = response.config, rest = __rest(response, ["data", "headers", "config"]);
return __assign(__assign({}, rest), { headers: sanitizeHeaders(headers), config: sanitizeConfig(config), data: truncateData(data) });
}
exports.sanitizeResponse = sanitizeResponse;
/**
* Extract relevant information from a rejected Axios error
*/
function parseAxiosError(error) {
var _a;
var errorInfo = {
name: error.name,
message: error.message,
code: error.code,
};
if (error.response) {
// Server responded with a status code outside of 2xx
var _b = error.response, status_1 = _b.status, statusText = _b.statusText, headers = _b.headers, data = _b.data;
errorInfo.status = status_1;
errorInfo.statusText = statusText;
errorInfo.headers = sanitizeHeaders(headers);
errorInfo.data = truncateData(data);
if (error.config) {
errorInfo.request = {
url: error.config.url,
method: (_a = error.config.method) === null || _a === void 0 ? void 0 : _a.toUpperCase(),
baseURL: error.config.baseURL,
headers: sanitizeHeaders(error.config.headers),
};
}
}
else if (error.request) {
// Request was made but no response received
errorInfo.request = '[Request sent, no response]';
errorInfo.type = 'network';
}
else {
// Error in setting up the request
errorInfo.type = 'client';
}
// Include any custom properties from the error
Object.entries(error).forEach(function (_a) {
var key = _a[0], value = _a[1];
if (!errorInfo[key] && !['response', 'request', 'config', 'isAxiosError'].includes(key)) {
errorInfo[key] = truncateData(value);
}
});
return errorInfo;
}
exports.parseAxiosError = parseAxiosError;
//# sourceMappingURL=error-utils.js.map