@apite/magento2-utility
Version:
Shopgate WebCheckout utility for Magento 2 extensions
107 lines (94 loc) • 3.21 kB
JavaScript
const get = require('lodash.get')
/**
* @param {string?} extensionName
*/
const logDecorator = (extensionName = '@apite-magento2-utility') => {
/**
* @param {AxiosResponse|Error} response
* @return {{extension: string}|FormattedAxiosResponse}
*/
const decorateError = response => {
if (response.statusText) {
return {
extension: extensionName,
...formatAxiosResponse(response)
}
}
return decorateMessage(response.message)
}
/**
* @param {string} message
* @return {{extension: string, messages: string[]}}
*/
const decorateMessage = message => ({
extension: extensionName,
message
})
/**
* Just a sprintf mimic
* @param {string} message
* @param {string[]} parameters
*/
const sprintf = (message, parameters) => {
return message.replace(/%\d+/g, (match) => {
const index = parseInt(match.slice(1)) - 1
return parameters[index] || match
})
}
/**
* @param {AxiosResponse} err
* @returns {FormattedAxiosRequest & FormattedAxiosResponse}
*/
const formatAxiosResponse = err => (
{
...formatAxiosRequest(err.config),
status: String(err.status),
statusText: err.statusText,
message: get(err, 'data.parameters') ? sprintf(err.data.message, err.data.parameters) : get(err, 'data.message'),
errors: (get(err, 'data.errors') || []).map(item => _cleanMessage(item.message)),
textResponse: typeof err.data === 'string' ? _cleanMessage(err.data) : undefined
}
)
/**
* @param {AxiosRequestConfig} request
* @returns {FormattedAxiosRequest}
*/
const formatAxiosRequest = request => {
const variables = get(request, 'data.variables')
return {
call: request.method.toUpperCase() + ' ' + [request.baseURL, request.url].join('/'),
headers: {
...request.headers.Authorization ? { Authorization: '***' + request.headers.Authorization.slice(-10) } : {},
Store: request.headers.Store
},
params: request.params,
data: {
query: _cleanMessage(get(request, 'data.query') || (typeof request.data === 'string' ? request.data : '')),
variables: variables ? _cleanMessage(JSON.stringify(variables)) : undefined
}
}
}
/**
* @param {string} message
* @return {string}
* @private
*/
const _cleanMessage = (message) => {
// Remove newline characters
let parsedQuery = message.replace(/\\n/g, '')
// Remove extra spaces
parsedQuery = parsedQuery.replace(/\s+/g, ' ').trim()
// obfuscate sensitive data
const sensitiveData = ['password', 'cartId']
sensitiveData.forEach(key => {
parsedQuery = parsedQuery.replace(new RegExp(`"${key}":\\s*"[^"]+"`, 'g'), `"${key}": "***"`)
})
parsedQuery = parsedQuery.length > 250 ? parsedQuery.slice(0, 250) + '...' : parsedQuery
// obfuscate 32 character strings that are wrapped in quotes (probably cart hashes)
parsedQuery = parsedQuery.replace(/"\w{32}"/, '"***"')
return parsedQuery !== '' ? parsedQuery : undefined
}
return { decorateError, decorateMessage, formatAxiosResponse, formatAxiosRequest }
}
module.exports = logDecorator