UNPKG

@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
"use strict"; 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