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

lambda-wrap

Package Overview
Dependencies
Maintainers
3
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lambda-wrap - npm Package Compare versions

Comparing version 1.1.0 to 2.0.0-alpha.1

jsconfig.json

18

index.js
'use strict';
const error = require('./lib/error');
const LambdaWrap = require('./lib/lambdaWrap');
const lambdaWrap = require('./lib/lambdaWrap');
module.exports = { LambdaWrap, error };
let warned = false;
module.exports = {
LambdaWrap (...args) {
if (!warned) {
console.warn('Using `LambdaWrap` is deprecated. Please use `lambdaWrap` instead.'); // eslint-disable-line no-console
warned = true;
}
return lambdaWrap(...args);
},
error,
lambdaWrap
};
'use strict';
const errorResponse = (error, event, context, callback, logger) => {
const { headers } = event;
const errorResponse = (error, event, context, callback, logger, options) => {
const headers = options.headers || {};
const {
path,
httpMethod,
body: eventBody,
headers: requestHeaders,
queryStringParameters,
pathParameters
} = event;
const { status, message, stack } = error;
const statusCode = status || 500;
const body = { message, code: statusCode };
logger.error(body);
const body = {
error: message,
code: statusCode
};
if (event.isOffline) {
const logMethod = statusCode < 500 ? 'warn' : 'error';
const log = {
status,
path,
httpMethod,
queryStringParameters,
pathParameters,
stack
};
if (event.verboseLog) {
Object.assign(log, {
eventBody,
headers,
requestHeaders
});
}
logger[logMethod](`Handler error: ${message}`, log);
if (event.verboseError) {
body.stack = stack;
}
Object.assign(headers, {
'Content-type': 'application/json; charset=utf-8'
});
const res = {

@@ -16,0 +52,0 @@ statusCode,

127

lib/lambdaWrap.js
'use strict';
const co = require('co');
const defaultResponse = require('./response');
const defaultErrorResponse = require('./errorResponse');
const wrapFunction = require('./wrapFunction');

@@ -11,5 +10,27 @@ const MIDDLEWARE = 'middleware';

const WRAP = 'wrap';
const FINALLY = 'finally';
function reductor (event, context, input = null) {
return [
(acc, cur) => {
switch (cur.type) {
case MIDDLEWARE:
return acc.then(() => cur.fn(event, context));
case WRAP:
return acc.then(() => cur.fn(event, context));
case CATCH:
return acc.catch(err => cur.fn(err, event, context));
case FINALLY:
return acc.then(([err, res]) => cur.fn(err, res, event, context)
.then(modify => modify || [err, res]));
default:
return acc.then(() => Promise.reject(new TypeError('Unkown function type')));
}
},
Promise.resolve(input)
];
}
/**
* `LambdaWrap` constructor. You can pass options to override or assign new
* `lambdaWrap` function. You can pass options to override or assign new
* attributes to `event` object. For example add custom headers:

@@ -22,3 +43,3 @@ *

*
* const wrap = new LambdaWrap({ headers });
* const wrap = lambdaWrap({ headers });
* </code></pre>

@@ -37,19 +58,15 @@ *

* <pre><code>
* const handler = wrap(customGeneratorFunction);
* const handler = wrap(async (event) => {
* return {
* body: 'Hello world'
* };
* });
* </pre></code>
*
* @constructor
* @param {Object} [options={}] - Use to override or assign new attributes
* to `event` object. E.g. headers.
*
* @returns {Object} - New instance of `LambdaWrap`.
* @param {LambdaWrapOptions} [options] - Use to override or assign new attributes
* @returns {Function} - the wrap function
*/
function LambdaWrap (options = {}) {
function lambdaWrap (options = {}) {
/**
*
* @param {Function} fn - Function to be wrapped and used as a lambda handler.
*
* @returns {Function} - Lambda handler.
*/
const wrap = (fn) => {

@@ -59,3 +76,3 @@

type: WRAP,
fn: co.wrap(fn)
fn: wrapFunction(fn)
};

@@ -70,13 +87,17 @@

_catchHandlers,
_finallyHandlers,
logger
} = wrap;
Object.assign(context, { callbackWaitsForEmptyEventLoop: false });
if (typeof options.callbackWaitsForEmptyEventLoop === 'boolean') {
Object.assign(context, {
callbackWaitsForEmptyEventLoop: options.callbackWaitsForEmptyEventLoop
});
}
Object.keys(options).forEach((option) => {
if (event[option]) {
Object.assign(event[option], options[option]);
} else {
event[option] = options[option]; // eslint-disable-line no-param-reassign
}
Object.assign(event, {
verboseError: !!(
options.verboseError || options.isOffline), // isOffline is deprecated
verboseLog: !!(
options.verboseLog || options.isOffline) // isOffline is deprecated
});

@@ -86,23 +107,28 @@

.concat(wrapped, _catchHandlers)
.reduce((acc, cur) => {
switch (cur.type) {
case MIDDLEWARE:
return acc.then(() => cur.fn(event, context));
case WRAP:
return acc.then(() => cur.fn(event, context));
case CATCH:
return acc.catch(err => cur.fn(err, event, context));
default:
return acc.then(() => Promise.reject(new TypeError('Unkown function type')));
}
}, Promise.resolve());
.reduce(...reductor(event, context));
let cb = callback;
if (_finallyHandlers.length > 0) {
cb = (err, res) => {
_finallyHandlers
.reduce(...reductor(event, context, [err, res]))
.then(([e, r]) => process.nextTick(() => callback(e, r)))
.catch((e) => {
const message = `Finally callback failed: ${e.message}`;
console.error(message, e); // eslint-disable-line no-console
if (logger !== console) {
logger.error(message, e);
}
callback(e);
});
};
}
return promisesToResolve
.then(data => responseHandler(data, event, context, callback, logger))
.catch(err => errorResponseHandler(err, event, context, callback, logger));
.then(data => responseHandler(data, event, context, cb, logger, options))
.catch(err => errorResponseHandler(err, event, context, cb, logger, options));
};
};
Object.setPrototypeOf(wrap, LambdaWrap.prototype);
// Private, not meant to be accessed directly.

@@ -112,2 +138,3 @@ // Use wrap.before() and wrap.catch() instead.

wrap._catchHandlers = [];
wrap._finallyHandlers = [];

@@ -127,3 +154,3 @@ // Public, meant to be accessed directly.

* Override default logger object - `console`.
* MUST implement `log` and `error` methods.
* MUST implement `log`, `warn` and `error` methods.
* */

@@ -140,3 +167,3 @@ wrap.logger = console;

type: MIDDLEWARE,
fn: co.wrap(fn)
fn: wrapFunction(fn)
});

@@ -153,9 +180,21 @@ };

type: CATCH,
fn: co.wrap(fn)
fn: wrapFunction(fn)
});
};
/**
* Add finally method, which will be called after each request
*
* @param {Function} fn - Middleware function.
*/
wrap.finally = (fn) => {
wrap._finallyHandlers.push({
type: FINALLY,
fn: wrapFunction(fn)
});
};
return wrap;
}
module.exports = LambdaWrap;
module.exports = lambdaWrap;

@@ -6,7 +6,7 @@ 'use strict';

// Content types
const TEXT_TYPE = { 'Content-Type': 'text/plain' };
const JSON_TYPE = { 'Content-Type': 'application/json' };
const TEXT_TYPE = { 'Content-Type': 'text/plain; charset=utf-8' };
const JSON_TYPE = { 'Content-Type': 'application/json; charset=utf-8' };
const response = (data, event, context, callback, logger) => {
const headers = event.headers || {};
const response = (data, event, context, callback, logger, options) => {
const headers = options.headers || {};

@@ -13,0 +13,0 @@ let res = data;

{
"name": "lambda-wrap",
"version": "1.1.0",
"version": "2.0.0-alpha.1",
"description": "AWS Serverless wrapper for async generators",
"main": "index.js",
"repository": {
"type": "git",
"url": "https://github.com/pragonauts/lambda-wrap.git"
},
"scripts": {

@@ -13,7 +17,7 @@ "test": "npm run test:lint && npm run test:coverage && npm run test:coverage:threshold",

"test:lint": "eslint ./lib/**/*.js ./test/**/*.js",
"doc:generate": "node ./bin/makeApiDoc.js"
"doc": "node ./bin/makeApiDoc.js"
},
"author": "Pragonauts <lukas.hykl@pragonauts.com> (https://pragonauts.com)",
"license": "ISC",
"dependencies": {
"author": "Pragonauts (https://pragonauts.com)",
"license": "MIT",
"optionalDependencies": {
"co": "^4.6.0"

@@ -23,14 +27,14 @@ },

"chai": "^4.1.2",
"eslint": "^4.13.1",
"eslint": "^4.19.1",
"eslint-config-airbnb": "^16.1.0",
"eslint-mocha": "^0.3.1",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-jsdoc": "^3.2.0",
"eslint-mocha": "^0.4.0",
"eslint-plugin-import": "^2.10.0",
"eslint-plugin-jsdoc": "^3.6.2",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-mocha": "^4.11.0",
"eslint-plugin-react": "^7.5.1",
"eslint-plugin-mocha": "^5.0.0",
"eslint-plugin-react": "^7.7.0",
"jsdoc-to-markdown": "^4.0.1",
"mocha": "^4.0.1",
"nyc": "^11.2.1"
"mocha": "^5.0.5",
"nyc": "^11.6.0"
}
}
# LambdaWrap
Simple async function wrapper for AWS lambda and serverless library
- allows using common middlewares (before, catch)
- allows to set common error response format
- supports generator functions using `co` (optional)
```javascript
const { lambdaWrap } = require('lambda-wrap');
const wrap = lambdaWrap({
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': 'true',
},
callbackWaitsForEmptyEventLoop: false, // usefull for mongodb
verboseError: true // include error stack in response (possible to )
verboseLog: true // include headers and body in error log
});
wrap.before((event) => {
if (event.body && `${event.headers['content-type']}`.match(/^application\/json/)) {
event.body = JSON.parse(event.body);
}
});
// or you can set custom logger
wrap.logger = console;
wrap.finally((error, response) => {
// close connections or send logs
});
module.exports.myHandler = wrap(async (event) => {
// return json body
return {
body: {
objectAttribute: true
}
};
})
```
-----------------

@@ -9,3 +54,3 @@

<dl>
<dt><a href="#LambdaWrap">LambdaWrap</a></dt>
<dt><a href="#lambdaWrap">lambdaWrap</a></dt>
<dd></dd>

@@ -22,20 +67,21 @@ </dl>

<a name="LambdaWrap"></a>
<a name="lambdaWrap"></a>
## LambdaWrap
**Kind**: global class
## lambdaWrap
**Kind**: global class
* [LambdaWrap](#LambdaWrap)
* [new LambdaWrap([options])](#new_LambdaWrap_new)
* [~wrap(fn)](#LambdaWrap..wrap) ⇒ <code>function</code>
* [.responseHandler](#LambdaWrap..wrap.responseHandler)
* [.errorResponseHandler](#LambdaWrap..wrap.errorResponseHandler)
* [.logger](#LambdaWrap..wrap.logger)
* [.before(fn)](#LambdaWrap..wrap.before)
* [.catch(fn)](#LambdaWrap..wrap.catch)
* [lambdaWrap](#lambdaWrap)
* [new lambdaWrap([options])](#new_lambdaWrap_new)
* [~wrap(fn)](#lambdaWrap..wrap) ⇒ <code>lambdaHandler</code>
* [.responseHandler](#lambdaWrap..wrap.responseHandler)
* [.errorResponseHandler](#lambdaWrap..wrap.errorResponseHandler)
* [.logger](#lambdaWrap..wrap.logger)
* [.before(fn)](#lambdaWrap..wrap.before)
* [.catch(fn)](#lambdaWrap..wrap.catch)
* [.finally(fn)](#lambdaWrap..wrap.finally)
<a name="new_LambdaWrap_new"></a>
<a name="new_lambdaWrap_new"></a>
### new LambdaWrap([options])
`LambdaWrap` constructor. You can pass options to override or assign new
### new lambdaWrap([options])
`lambdaWrap` function. You can pass options to override or assign new
attributes to `event` object. For example add custom headers:

@@ -48,3 +94,3 @@

const wrap = new LambdaWrap({ headers });
const wrap = lambdaWrap({ headers });
</code></pre>

@@ -63,16 +109,20 @@

<pre><code>
const handler = wrap(customGeneratorFunction);
const handler = wrap(async (event) => {
return {
body: 'Hello world'
};
});
</pre></code>
**Returns**: <code>Object</code> - - New instance of `LambdaWrap`.
**Returns**: <code>wrapFn</code> - - the wrap function
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| [options] | <code>Object</code> | <code>{}</code> | Use to override or assign new attributes to `event` object. E.g. headers. |
| Param | Type | Description |
| --- | --- | --- |
| [options] | <code>LambdaWrapOptions</code> | Use to override or assign new attributes to `event` object. E.g. headers. |
<a name="LambdaWrap..wrap"></a>
<a name="lambdaWrap..wrap"></a>
### LambdaWrap~wrap(fn) ⇒ <code>function</code>
**Kind**: inner method of [<code>LambdaWrap</code>](#LambdaWrap)
**Returns**: <code>function</code> - - Lambda handler.
### lambdaWrap~wrap(fn) ⇒ <code>lambdaHandler</code>
**Kind**: inner method of [<code>lambdaWrap</code>](#lambdaWrap)
**Returns**: <code>lambdaHandler</code> - - Lambda handler.

@@ -84,10 +134,11 @@ | Param | Type | Description |

* [~wrap(fn)](#LambdaWrap..wrap) ⇒ <code>function</code>
* [.responseHandler](#LambdaWrap..wrap.responseHandler)
* [.errorResponseHandler](#LambdaWrap..wrap.errorResponseHandler)
* [.logger](#LambdaWrap..wrap.logger)
* [.before(fn)](#LambdaWrap..wrap.before)
* [.catch(fn)](#LambdaWrap..wrap.catch)
* [~wrap(fn)](#lambdaWrap..wrap) ⇒ <code>lambdaHandler</code>
* [.responseHandler](#lambdaWrap..wrap.responseHandler)
* [.errorResponseHandler](#lambdaWrap..wrap.errorResponseHandler)
* [.logger](#lambdaWrap..wrap.logger)
* [.before(fn)](#lambdaWrap..wrap.before)
* [.catch(fn)](#lambdaWrap..wrap.catch)
* [.finally(fn)](#lambdaWrap..wrap.finally)
<a name="LambdaWrap..wrap.responseHandler"></a>
<a name="lambdaWrap..wrap.responseHandler"></a>

@@ -97,4 +148,4 @@ #### wrap.responseHandler

**Kind**: static property of [<code>wrap</code>](#LambdaWrap..wrap)
<a name="LambdaWrap..wrap.errorResponseHandler"></a>
**Kind**: static property of [<code>wrap</code>](#lambdaWrap..wrap)
<a name="lambdaWrap..wrap.errorResponseHandler"></a>

@@ -104,11 +155,11 @@ #### wrap.errorResponseHandler

**Kind**: static property of [<code>wrap</code>](#LambdaWrap..wrap)
<a name="LambdaWrap..wrap.logger"></a>
**Kind**: static property of [<code>wrap</code>](#lambdaWrap..wrap)
<a name="lambdaWrap..wrap.logger"></a>
#### wrap.logger
Override default logger object - `console`.
MUST implement `log` and `error` methods.
MUST implement `log`, `warn` and `error` methods.
**Kind**: static property of [<code>wrap</code>](#LambdaWrap..wrap)
<a name="LambdaWrap..wrap.before"></a>
**Kind**: static property of [<code>wrap</code>](#lambdaWrap..wrap)
<a name="lambdaWrap..wrap.before"></a>

@@ -118,3 +169,3 @@ #### wrap.before(fn)

**Kind**: static method of [<code>wrap</code>](#LambdaWrap..wrap)
**Kind**: static method of [<code>wrap</code>](#lambdaWrap..wrap)

@@ -125,3 +176,3 @@ | Param | Type | Description |

<a name="LambdaWrap..wrap.catch"></a>
<a name="lambdaWrap..wrap.catch"></a>

@@ -131,3 +182,3 @@ #### wrap.catch(fn)

**Kind**: static method of [<code>wrap</code>](#LambdaWrap..wrap)
**Kind**: static method of [<code>wrap</code>](#lambdaWrap..wrap)

@@ -138,2 +189,13 @@ | Param | Type | Description |

<a name="lambdaWrap..wrap.finally"></a>
#### wrap.finally(fn)
Add finally method, which will be called after each request
**Kind**: static method of [<code>wrap</code>](#lambdaWrap..wrap)
| Param | Type | Description |
| --- | --- | --- |
| fn | <code>function</code> | Middleware function. |
<a name="error"></a>

@@ -144,3 +206,3 @@

**Kind**: global function
**Kind**: global function

@@ -147,0 +209,0 @@ | Param | Type | Description |

@@ -5,6 +5,6 @@ 'use strict';

const LambdaWrap = require('../../lib/lambdaWrap');
const lambdaWrap = require('../../lib/lambdaWrap');
describe('LambdaWrap', () => {
let wrap;
let wrap = lambdaWrap();
let event;

@@ -18,3 +18,3 @@ let context;

// Initialize new Lambda wrap and mock event and context objects
wrap = new LambdaWrap();
wrap = lambdaWrap();
event = {};

@@ -25,3 +25,4 @@ context = {};

log: () => {},
error: () => {}
error: (e) => { console.warn(e); }, // eslint-disable-line
warn: () => {}
};

@@ -53,60 +54,3 @@

describe('constructor', () => {
it('should return an instance of LambdaWrap', () => {
assert.instanceOf(wrap, LambdaWrap);
});
it('should be able to assign new attributes to options', (done) => {
event = {
headers: { 'Access-Control-Allow-Origin': '*' }
};
wrap = new LambdaWrap({
someOption: 'value'
});
wrap.logger = loggerMock;
const handler = wrap(function* (e) {
const { headers, someOption } = e;
assert.equal(headers['Access-Control-Allow-Origin'], '*');
assert.equal(someOption, 'value');
done();
return {
statusCode: 200,
message: 'test'
};
});
handler(event, context, () => {});
});
it('should be able to assign new values options\' attributes', (done) => {
event = {
headers: { 'Access-Control-Allow-Origin': '*' }
};
wrap = new LambdaWrap({
headers: { 'X-Auth-Token': '1234' }
});
wrap.logger = loggerMock;
const handler = wrap(function* (e) {
const { headers } = e;
assert.equal(headers['X-Auth-Token'], '1234');
assert.equal(headers['Access-Control-Allow-Origin'], '*');
done();
return {
statusCode: 200,
message: 'test'
};
});
handler(event, context, () => {});
});
it('should set default response handler', () => {

@@ -141,2 +85,21 @@ const { name } = wrap.responseHandler;

it('should return a function');
it('should accept async functions', (done) => {
const handler = wrap(async (ev) => {
const { body } = ev;
await new Promise(r => setTimeout(r, 10));
return {
body
};
});
const callback = (ctx, data) => {
assert.equal(data.body, 'Hello');
done();
};
handler({ body: 'Hello' }, context, callback);
});
});

@@ -173,3 +136,3 @@

assert.equal(body.message, 'Middleware error');
assert.equal(body.error, 'Middleware error');
done();

@@ -191,3 +154,3 @@ };

assert.equal(body.message, 'Middleware error');
assert.equal(body.error, 'Middleware error');
done();

@@ -224,24 +187,38 @@ };

it('should execute middlewares in order', (done) => {
});
describe('finally', () => {
it('should be called before the callback if set', (done) => {
let finallyCalls = 0;
const callback = () => {
assert.equal(finallyCalls, 1);
done();
};
wrap.before(function* (e) {
const result = yield doAsyncStuff('resolve', true);
wrap.finally(() => {
finallyCalls++;
});
if (result) {
e.options.headers = {
'X-Auth-Token': 'xyz123'
};
}
const handler = wrap(function* () {
throw new Error('Error');
});
wrap.before(function* (e) {
yield doAsyncStuff('resolve', true);
assert.equal(e.options.headers['X-Auth-Token'], 'xyz123');
handler(event, context, callback);
});
it('should be able to modify response', (done) => {
const test = {};
const callback = (err, res) => {
assert.strictEqual(res, test);
done();
};
wrap.finally(() => [null, test]);
const handler = wrap(function* () {
throw new Error('Error');
});
const handler = wrap(fn);
handler(event, context, callback);

@@ -256,3 +233,3 @@ });

assert.equal(body.message, 'Catch error');
assert.equal(body.error, 'Catch error');
done();

@@ -276,3 +253,3 @@ };

assert.equal(body.message, 'Catch error');
assert.equal(body.error, 'Catch error');
done();

@@ -320,3 +297,3 @@ };

assert.equal(body.message, 'Second error');
assert.equal(body.error, 'Second error');
done();

@@ -323,0 +300,0 @@ };

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