classy-pay-core
Version:
Shared tools used in ClassyPay-related projects
296 lines • 10.1 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.unpromisify = exports.runFunctionAfterDelay = exports.sequelizeCloneDeep = exports.recurse = exports.requestWithLogs = exports.redact = exports.omitDeepWithKeys = exports.stringToBoolean = exports.JSONParseBig = exports.normalizeUrl = exports.isJSONString = exports.safeStrConcat = void 0;
const axios_1 = __importDefault(require("axios"));
const _ = __importStar(require("lodash"));
const safeStrConcat = (strings) => {
let output = '';
for (const s of strings) {
if (s !== null && s !== undefined) {
output = output + s;
}
}
return output;
};
exports.safeStrConcat = safeStrConcat;
const isJSONString = (jsonString) => {
try {
const o = JSON.parse(jsonString);
if (o && typeof o === 'object') {
return true;
}
}
catch (e) { }
return false;
};
exports.isJSONString = isJSONString;
const normalizeUrl = (inputUrl) => {
const m = inputUrl.match(/^(https?:\/\/)([^:/?#]*)(:[0-9]+)?([^?#]*)?(\?[^?]+)?$/);
if (m) {
let path = '/';
if (m[4]) {
if (!m[4].startsWith('/')) {
throw new Error(`Path part of URL didn't start with /`);
}
path = m[4].replace(/\/\/+/g, '/');
}
return (0, exports.safeStrConcat)([
m[1],
m[2],
m[3],
path,
m[5],
]);
}
else {
throw new Error(`URL "${inputUrl}" didn't look like a URL and couldn't be normalized`);
}
};
exports.normalizeUrl = normalizeUrl;
const jsonParse = require('json-bigint')({ storeAsString: true }).parse;
const JSONParseBig = (json) => require('json-bigint')({ storeAsString: true }).parse(json);
exports.JSONParseBig = JSONParseBig;
const stringToBoolean = (input, defaultValue = false) => {
if (input) {
if (_.toLower(input) === 'true') {
return true;
}
const n = parseFloat(input);
if (isFinite(n) && !isNaN(n) && n > 0) {
return true;
}
return false;
}
return defaultValue;
};
exports.stringToBoolean = stringToBoolean;
const omitDeepWithKeys = (obj, excludeKeys, replacementValue) => {
const stackSet = new Set();
const newObj = _.cloneDeep(obj);
const omitFn = (value) => {
if (!_.isObject(value) || _.isFunction(value) || stackSet.has(value)) {
return;
}
const valueAsRecord = value;
excludeKeys.forEach(key => {
if (replacementValue && valueAsRecord[key] !== undefined) {
valueAsRecord[key] = replacementValue;
}
else {
delete valueAsRecord[key];
}
});
stackSet.add(valueAsRecord);
for (const key of Object.keys(valueAsRecord)) {
omitFn(valueAsRecord[key]);
}
};
omitFn(newObj);
return newObj;
};
exports.omitDeepWithKeys = omitDeepWithKeys;
const redact = (obj) => (0, exports.omitDeepWithKeys)(obj, [
'Authorization',
'accountNumber',
'address1',
'address2',
'address3',
'address4',
'city',
'email',
'token',
'province',
'routingNumber',
'state',
'zip',
'processorDetails',
'source',
], '*** REDACTED ***');
exports.redact = redact;
const requestWithLogs = async (options, log) => {
var _a;
let logString;
if (log) {
const location = options.url;
logString = `${(_a = options.method) === null || _a === void 0 ? void 0 : _a.toUpperCase()} ${location}`;
log.info((0, exports.redact)({ request: options }), `Request ${logString}`);
}
let response;
let error;
try {
const retValue = await (0, axios_1.default)(options);
response = retValue;
return retValue;
}
catch (e) {
if (e instanceof Error) {
error = e;
throw e;
}
else {
error = new Error('An unknown error occurred');
throw error;
}
}
finally {
if (log) {
let statusCode = response ? response.status : undefined;
if (!statusCode && error && axios_1.default.isAxiosError(error) && error.response) {
statusCode = error.response.status;
}
if (statusCode === 200 && error === undefined) {
const toRedactResponse = _.cloneDeep(response);
if ((toRedactResponse === null || toRedactResponse === void 0 ? void 0 : toRedactResponse.data) && (0, exports.isJSONString)(JSON.stringify(toRedactResponse.data))) {
toRedactResponse.data = JSON.parse(JSON.stringify(toRedactResponse.data));
}
log.info((0, exports.redact)({ request: options, response: toRedactResponse }), `Response (Good) ${logString}`);
}
else {
log.error((0, exports.redact)({ request: options, response, error }), `Response (Bad${statusCode ? ' - ' + statusCode : ''}) ${logString}`);
}
}
}
};
exports.requestWithLogs = requestWithLogs;
const recurse = (input, visitor, options) => {
if (input) {
const action = visitor('ROOT', input);
if (action === 'RECURSE_DEEPER') {
_recurseImpl(undefined, input, visitor, options);
}
}
};
exports.recurse = recurse;
const _recurseImpl = (parent, input, visitor, options) => {
if (Array.isArray(input)) {
const inputArray = input;
for (let i = 0; i < inputArray.length; i++) {
const action = visitor('ARRAY', inputArray[i], i, inputArray);
if (action === 'RECURSE_DEEPER') {
_recurseImpl(inputArray, inputArray[i], visitor, options);
}
}
}
else if (_.isObject(input) && !_.isFunction(input)) {
const inputObject = input;
const visitNonEnumerableNodes = options ? options.visitNonEnumerableNodes : false;
for (const key of visitNonEnumerableNodes ? Object.getOwnPropertyNames(inputObject) : Object.keys(input)) {
const action = visitor('OBJECT', inputObject[key], key, inputObject);
if (action === 'RECURSE_DEEPER') {
_recurseImpl(inputObject, inputObject[key], visitor, options);
}
}
}
};
const sequelizeCloneDeep = (input) => {
const clonedNodes = new Map();
let clonedRootNode;
(0, exports.recurse)(input, (type, value, keyOrIndex, parent) => {
let clonedValue;
let retval = 'RECURSE_DEEPER';
if (value === undefined || value === null) {
clonedValue = value;
}
else if (keyOrIndex === 'prototype') {
return 'STOP'; // prevent prototype pollution
}
else if (clonedNodes.get(value)) {
clonedValue = clonedNodes.get(value);
retval = 'STOP';
}
else if (value.toJSON) {
clonedValue = value.toJSON();
clonedNodes.set(value, clonedValue);
retval = 'STOP';
}
else {
clonedValue = _.clone(value);
clonedNodes.set(value, clonedValue);
}
let clonedParent;
if (type === 'ROOT') {
clonedNodes.set(value, clonedValue);
clonedRootNode = clonedValue;
}
else {
clonedParent = clonedNodes.get(parent);
if (!clonedParent) {
throw new Error(`Couldn't find cloned parent while recursing`);
}
clonedParent[keyOrIndex ? keyOrIndex : 0] = clonedValue;
}
return retval;
});
return clonedRootNode;
};
exports.sequelizeCloneDeep = sequelizeCloneDeep;
const runFunctionAfterDelay = (ms, func) => {
return new Promise((resolve, reject) => {
setTimeout(async () => {
try {
const result = await func();
resolve(result);
}
catch (e) {
reject(e);
}
}, ms);
});
};
exports.runFunctionAfterDelay = runFunctionAfterDelay;
const unpromisify = async (f, callback) => {
let result;
let error;
try {
result = await f();
}
catch (e) {
error = e;
}
finally {
if (error instanceof Error) {
callback(error, result);
}
else {
callback(new Error('An unknown error occurred'), result);
}
}
};
exports.unpromisify = unpromisify;
//# sourceMappingURL=utils.js.map