New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@middy/input-output-logger

Package Overview
Dependencies
Maintainers
3
Versions
214
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@middy/input-output-logger - npm Package Compare versions

Comparing version 5.1.0 to 5.2.0

257

index.js

@@ -0,107 +1,164 @@

import { Transform } from 'node:stream'
const defaults = {
logger: console.log,
awsContext: false,
omitPaths: [],
mask: undefined,
replacer: undefined
};
const inputOutputLoggerMiddleware = (opts = {})=>{
const { logger, awsContext, omitPaths, mask, replacer } = {
...defaults,
...opts
};
if (typeof logger !== 'function') {
throw new Error('logger must be a function', {
cause: {
package: '@middy/input-output-logger'
}
});
logger: console.log,
awsContext: false,
omitPaths: [],
mask: undefined,
replacer: undefined
}
const inputOutputLoggerMiddleware = (opts = {}) => {
const { logger, awsContext, omitPaths, mask, replacer } = {
...defaults,
...opts
}
if (typeof logger !== 'function') {
throw new Error('logger must be a function', {
cause: {
package: '@middy/input-output-logger'
}
})
}
const omitPathTree = buildPathTree(omitPaths)
// needs `omitPathTree`, `logger`
const omitAndLog = (param, request) => {
const message = { [param]: request[param] }
if (awsContext) {
message.context = pick(request.context, awsContextKeys)
}
const omitPathTree = buildPathTree(omitPaths);
const omitAndLog = (param, request)=>{
const message = {
[param]: request[param]
};
if (awsContext) {
message.context = pick(request.context, awsContextKeys);
let cloneMessage = message
if (omitPaths.length) {
cloneMessage = structuredClone(message, replacer) // Full clone to prevent nested mutations
omit(cloneMessage, { [param]: omitPathTree[param] })
}
logger(cloneMessage)
}
// needs `mask`
const omit = (obj, pathTree = {}) => {
if (Array.isArray(obj) && pathTree['[]']) {
for (let i = 0, l = obj.length; i < l; i++) {
omit(obj[i], pathTree['[]'])
}
} else if (isObject(obj)) {
for (const key in pathTree) {
if (pathTree[key] === true) {
if (mask) {
obj[key] = mask
} else {
delete obj[key]
}
} else {
omit(obj[key], pathTree[key])
}
let cloneMessage = message;
if (omitPaths.length) {
cloneMessage = structuredClone(message, replacer);
omit(cloneMessage, {
[param]: omitPathTree[param]
});
}
logger(cloneMessage);
};
const omit = (obj, pathTree = {})=>{
if (Array.isArray(obj) && pathTree['[]']) {
for(let i = 0, l = obj.length; i < l; i++){
omit(obj[i], pathTree['[]']);
}
} else if (isObject(obj)) {
for(const key in pathTree){
if (pathTree[key] === true) {
if (mask) {
obj[key] = mask;
} else {
delete obj[key];
}
} else {
omit(obj[key], pathTree[key]);
}
}
}
};
const inputOutputLoggerMiddlewareBefore = async (request)=>omitAndLog('event', request);
const inputOutputLoggerMiddlewareAfter = async (request)=>omitAndLog('response', request);
const inputOutputLoggerMiddlewareOnError = async (request)=>{
if (request.response === undefined) return;
omitAndLog('response', request);
};
return {
before: inputOutputLoggerMiddlewareBefore,
after: inputOutputLoggerMiddlewareAfter,
onError: inputOutputLoggerMiddlewareOnError
};
};
}
}
}
const inputOutputLoggerMiddlewareBefore = async (request) => {
omitAndLog('event', request)
}
const inputOutputLoggerMiddlewareAfter = async (request) => {
if (
request.response?._readableState ??
request.response?.body?._readableState
) {
passThrough(request, omitAndLog)
} else {
omitAndLog('response', request)
}
}
const inputOutputLoggerMiddlewareOnError = async (request) => {
if (request.response === undefined) return
inputOutputLoggerMiddlewareAfter(request)
}
return {
before: inputOutputLoggerMiddlewareBefore,
after: inputOutputLoggerMiddlewareAfter,
onError: inputOutputLoggerMiddlewareOnError
}
}
// https://docs.aws.amazon.com/lambda/latest/dg/nodejs-context.html
const awsContextKeys = [
'functionName',
'functionVersion',
'invokedFunctionArn',
'memoryLimitInMB',
'awsRequestId',
'logGroupName',
'logStreamName',
'identity',
'clientContext',
'callbackWaitsForEmptyEventLoop'
];
const pick = (originalObject = {}, keysToPick = [])=>{
const newObject = {};
for (const path of keysToPick){
if (originalObject[path] !== undefined) {
newObject[path] = originalObject[path];
'functionName',
'functionVersion',
'invokedFunctionArn',
'memoryLimitInMB',
'awsRequestId',
'logGroupName',
'logStreamName',
'identity',
'clientContext',
'callbackWaitsForEmptyEventLoop'
]
// move to util, if ever used elsewhere
const pick = (originalObject = {}, keysToPick = []) => {
const newObject = {}
for (const path of keysToPick) {
// only supports first level
if (originalObject[path] !== undefined) {
newObject[path] = originalObject[path]
}
}
return newObject
}
const isObject = (value) =>
value && typeof value === 'object' && value.constructor === Object
const buildPathTree = (paths) => {
const tree = {}
for (let path of paths.sort().reverse()) {
// reverse to ensure conflicting paths don't cause issues
if (!Array.isArray(path)) path = path.split('.')
if (path.includes('__proto__')) continue
path
.slice(0) // clone
.reduce((a, b, idx) => {
if (idx < path.length - 1) {
a[b] ??= {}
return a[b]
}
a[b] = true
return true
}, tree)
}
return tree
}
const passThrough = (request, omitAndLog) => {
// required because `core` remove body before `flush` is triggered
const hasBody = request.response?.body
let body = ''
const listen = new Transform({
objectMode: false,
transform (chunk, encoding, callback) {
body += chunk
this.push(chunk, encoding)
callback()
},
flush (callback) {
if (hasBody) {
omitAndLog('response', { response: { ...request.response, body } })
} else {
omitAndLog('response', { response: body })
}
callback()
}
return newObject;
};
const buildPathTree = (paths)=>{
const tree = {};
for (let path of paths.sort().reverse()){
if (!Array.isArray(path)) path = path.split('.');
if (path.includes('__proto__')) continue;
path.slice(0).reduce((a, b, idx)=>{
if (idx < path.length - 1) {
a[b] ??= {};
return a[b];
}
a[b] = true;
return true;
}, tree);
}
return tree;
};
const isObject = (value)=>value && typeof value === 'object' && value.constructor === Object;
export default inputOutputLoggerMiddleware;
})
if (hasBody) {
request.response.body = request.response.body.pipe(listen)
} else {
request.response = request.response.pipe(listen)
}
}
export default inputOutputLoggerMiddleware
{
"name": "@middy/input-output-logger",
"version": "5.1.0",
"version": "5.2.0",
"description": "Input and output logger middleware for the middy framework",

@@ -63,6 +63,7 @@ "type": "module",

"devDependencies": {
"@middy/core": "5.1.0",
"@datastream/core": "0.0.35",
"@middy/core": "5.2.0",
"@types/node": "^20.0.0"
},
"gitHead": "bbdaf5843914921804ba085dd58117273febe6b5"
"gitHead": "2d9096a49cd8fb62359517be96d6c93609df41f0"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc