From 77231a0b3818792f8281de539fbf438b6eb1a439 Mon Sep 17 00:00:00 2001 From: Eetu Tuomala Date: Fri, 16 Jun 2017 16:54:54 +0300 Subject: [PATCH 01/15] refactor backward compatibility --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cf2a06a..ae7e66f 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ to your AWS account as 'lambdaWrapper-test'. ## Release History +* 2017/07/16 - v0.1.3 - Allow context object in run * 2016/10/21 - v0.1.2 - Support for using promises * 2016/07/26 - v0.1.1 - Support for alternative handler. runHandler method for passing custom context. * 2016/04/26 - v0.1.0 - Support for running lambda functions also from AWS From 201fa6a64ad5f3ce38855cfeb8358c574b377904 Mon Sep 17 00:00:00 2001 From: Mariusz Nowak Date: Tue, 20 Jun 2017 09:44:15 +0200 Subject: [PATCH 02/15] Ensure consistent error handling --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 7e5ecd3..af3ee45 100644 --- a/index.js +++ b/index.js @@ -57,7 +57,9 @@ class Wrapped { if (err) { return callback(err); } - + if (data.FunctionError) { + return callback(Object.assign(new Error(JSON.parse(data.Payload).errorMessage), data)); + } return callback(null, JSON.parse(data.Payload)); }); } From 2ede7e3855167ad08fbc4556cfc0fcbca8a52270 Mon Sep 17 00:00:00 2001 From: mpuittinen Date: Sun, 9 Jul 2017 15:23:31 +0300 Subject: [PATCH 03/15] Return exceptions as errors via callback --- README.md | 5 ++++- index.js | 1 + package.json | 2 +- test/test-wrapper.js | 21 +++++++++++++++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ae7e66f..8cd3e31 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ If you want to pass a custom context to the Lambda module (only when running loc lambda.runHandler(event, customContext, callback) Documentation for valid propreties in the Lambda context object are documented here http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html + +Exceptions from within the module will be returned as errors via the callback / promise. ## Development @@ -46,7 +48,8 @@ to your AWS account as 'lambdaWrapper-test'. ## Release History -* 2017/07/16 - v0.1.3 - Allow context object in run +* 2017/07/09 - v0.2.0 - Return exceptions as errors via callback +* 2017/06/16 - v0.1.3 - Allow context object in run * 2016/10/21 - v0.1.2 - Support for using promises * 2016/07/26 - v0.1.1 - Support for alternative handler. runHandler method for passing custom context. * 2016/04/26 - v0.1.0 - Support for running lambda functions also from AWS diff --git a/index.js b/index.js index 7e5ecd3..da6bdc8 100644 --- a/index.js +++ b/index.js @@ -62,6 +62,7 @@ class Wrapped { }); } } catch (ex) { + callback(ex); throw (ex); } }); diff --git a/package.json b/package.json index 702d2a5..88239b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lambda-wrapper", - "version": "0.1.3", + "version": "0.2.0", "description": "Wrapper for running Amazon Lambda modules locally", "main": "index.js", "scripts": { diff --git a/test/test-wrapper.js b/test/test-wrapper.js index e7fac08..826d1e4 100644 --- a/test/test-wrapper.js +++ b/test/test-wrapper.js @@ -40,6 +40,13 @@ const testMod5 = { } }; +// causes exception +const testMod6 = { + handler: (event, context, callback) => { + throw 'TestException'; + } +} + describe('lambda-wrapper local', () => { it('init + run with success - callback', (done) => { wrapper.init(testMod1); @@ -202,6 +209,20 @@ describe('lambda-wrapper local', () => { }) .catch(done); }); + + it('wrap + run module 6 - exception', (done) => { + const w = wrapper.wrap(testMod6); + + w.run({ test: 'cbsuccess' }, { functionName: 'testing' }) + .then((response) => { + done('Did not return error'); + }, (error) => { + expect(error).to.be.equal('TestException'); + done(); + console.log(error); + }) + .catch(done); + }); }); if (process.env.RUN_LIVE) { From 426e4b924965d7a143aa3eb61636e6ea1599e27a Mon Sep 17 00:00:00 2001 From: mpuittinen Date: Sun, 9 Jul 2017 16:10:21 +0300 Subject: [PATCH 04/15] Do not throw error at all for exceptions (just callback) --- index.js | 3 +-- package.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index da6bdc8..0fae9f0 100644 --- a/index.js +++ b/index.js @@ -62,8 +62,7 @@ class Wrapped { }); } } catch (ex) { - callback(ex); - throw (ex); + return callback(ex); } }); } diff --git a/package.json b/package.json index 88239b2..8d74977 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lambda-wrapper", - "version": "0.2.0", + "version": "0.2.1", "description": "Wrapper for running Amazon Lambda modules locally", "main": "index.js", "scripts": { From cccab3ff1025676a0014cfcb8ee0b3d50813739a Mon Sep 17 00:00:00 2001 From: mpuittinen Date: Mon, 10 Jul 2017 12:58:33 +0300 Subject: [PATCH 05/15] Increase test timeout and change default region --- test/test-wrapper.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test-wrapper.js b/test/test-wrapper.js index 826d1e4..3c57390 100644 --- a/test/test-wrapper.js +++ b/test/test-wrapper.js @@ -242,12 +242,12 @@ if (process.env.RUN_LIVE) { expect(response.event.test).to.be.equal('livesuccess'); done(); }); - }); + }).timeout(3000); it('can call lambda functions deployed in AWS - promise', (done) => { const w = wrapper.wrap({ lambdaFunction: 'lambdaWrapper-test', - region: process.env.AWS_DEFAULT_REGION || 'eu-central-1' + region: process.env.AWS_DEFAULT_REGION || 'us-east-1' }); w.run({ test: 'livesuccess' }) @@ -256,6 +256,6 @@ if (process.env.RUN_LIVE) { expect(response.event.test).to.be.equal('livesuccess'); done(); }).catch(done); - }); + }).timeout(3000); }); } From 0e902ee6967f0ee65e7db3cdb57b1029c5d68cd6 Mon Sep 17 00:00:00 2001 From: Mariusz Nowak Date: Mon, 17 Jul 2017 17:03:43 +0200 Subject: [PATCH 06/15] Introduce input validation --- index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/index.js b/index.js index a3f515d..fb1092d 100644 --- a/index.js +++ b/index.js @@ -12,6 +12,11 @@ class Wrapped { if (mod[handler]) { this.handler = mod[handler]; + } else { + if (!this.lambdaModule.lambdaFunction) { + throw new Error("Invalid input. Expected either lambda module (with exposed handler) " + + "or AWS Lambda configuration (with provided 'lambdaFunction' name)"); + } } } From 21dcd01ece213c4f4f08285d274acdf7460ab29c Mon Sep 17 00:00:00 2001 From: simlu Date: Sat, 18 Nov 2017 16:27:02 -0800 Subject: [PATCH 07/15] Making aws-sdk a dependency It appears aws-sdk is not a dev dependency... --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8d74977..adeca04 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,10 @@ }, "homepage": "https://github.com/SC5/lambda-wrapper", "devDependencies": { - "aws-sdk": "^2.4.0", "chai": "3.5.0", "mocha": "2.4.5" }, - "dependencies": {} + "dependencies": { + "aws-sdk": "^2.4.0" + } } From 1a3248692c2ab559395a2b1add3053557b4f1fd1 Mon Sep 17 00:00:00 2001 From: mpuittinen Date: Thu, 23 Nov 2017 12:17:05 +0200 Subject: [PATCH 08/15] Update version to 0.2.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index adeca04..22fd81e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lambda-wrapper", - "version": "0.2.1", + "version": "0.2.2", "description": "Wrapper for running Amazon Lambda modules locally", "main": "index.js", "scripts": { From 0e914775212447873dcf60ec3b6f761c1ca0504c Mon Sep 17 00:00:00 2001 From: mpuittinen Date: Thu, 21 Dec 2017 14:29:13 +0200 Subject: [PATCH 09/15] Rebrand to Nordcloud --- README.md | 4 ++-- package.json | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 8cd3e31..a758ac9 100644 --- a/README.md +++ b/README.md @@ -60,5 +60,5 @@ to your AWS account as 'lambdaWrapper-test'. ## License -Copyright (c) 2016 [SC5](http://sc5.io/), licensed for users and contributors under MIT license. -https://github.com/SC5/lambda-wrapper/blob/master/LICENSE +Copyright (c) 2016 [Nordcloud](https://nordcloud.com/), licensed for users and contributors under MIT license. +https://github.com/nordcloud/lambda-wrapper/blob/master/LICENSE diff --git a/package.json b/package.json index 22fd81e..392d8b1 100644 --- a/package.json +++ b/package.json @@ -9,23 +9,23 @@ }, "repository": { "type": "git", - "url": "https://github.com/SC5/lambda-wrapper.git" + "url": "https://github.com/nordcloud/lambda-wrapper.git" }, "keywords": [ "AWS", "lambda", "local" ], - "author": "Mikael Puittinen (mikael.puittinen@sc5.io)", + "author": "Mikael Puittinen (https://nordcloud.com)", "contributors": [ - "Toni Ruottu (https://sc5.io)", - "Eetu Tuomala (https://sc5.io)" + "Toni Ruottu", + "Eetu Tuomala" ], "license": "MIT", "bugs": { - "url": "https://github.com/SC5/lambda-wrapper/issues" + "url": "https://github.com/nordcloud/lambda-wrapper/issues" }, - "homepage": "https://github.com/SC5/lambda-wrapper", + "homepage": "https://github.com/nordcloud/lambda-wrapper", "devDependencies": { "chai": "3.5.0", "mocha": "2.4.5" From 0cfea490844c910cb52ce38b5a9747dd42881b54 Mon Sep 17 00:00:00 2001 From: mpuittinen Date: Mon, 1 Jan 2018 12:30:10 +0200 Subject: [PATCH 10/15] Fix Travis url --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a758ac9..b777d28 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # lambda-wrapper -[![Build Status](https://travis-ci.org/SC5/lambda-wrapper.svg?branch=master)](https://travis-ci.org/SC5/lambda-wrapper) +[![Build Status](https://travis-ci.org/nordcloud/lambda-wrapper.svg?branch=master)](https://travis-ci.org/nordcloud/lambda-wrapper) Wrapper for running lambda modules locally or from AWS during development From fdca495f71f61135687b4ffe3864fd27c7e62214 Mon Sep 17 00:00:00 2001 From: Doug McCall Date: Sun, 6 May 2018 14:01:26 -0400 Subject: [PATCH 11/15] Add support for async wrapped handlers --- index.js | 18 ++++++++++++++++-- test/test-wrapper.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index a3f515d..a4435fd 100644 --- a/index.js +++ b/index.js @@ -36,8 +36,22 @@ class Wrapped { const lambdaContext = Object.assign({}, defaultContext, customContext); try { - if (this.handler) { - this.handler(event, lambdaContext, callback); + if (this.handler) { + const handlerResult = this.handler(event, lambdaContext, callback); + // Check if the result itself is a promise + if (handlerResult && handlerResult.then) { + handlerResult.then(function(data) { + // Avoid Maximum call stack size exceeded exceptions + return setImmediate(function() { + callback(null, data); + }); + }).catch(function(err) { + // Avoid Maximum call stack size exceeded exceptions + return setImmediate(function() { + callback(err); + }); + }); + } } else { if (this.lambdaModule.region) { AWS.config.update({ diff --git a/test/test-wrapper.js b/test/test-wrapper.js index 3c57390..feb4886 100644 --- a/test/test-wrapper.js +++ b/test/test-wrapper.js @@ -3,6 +3,8 @@ const wrapper = require('../index.js'); const expect = require('chai').expect; +const SUPPORTS_ASYNC = Number(process.versions.node.split('.', 1)[0]) >= 8; + const testMod1 = { handler: (event, context) => { if (event.test === 'success') { @@ -223,6 +225,48 @@ describe('lambda-wrapper local', () => { }) .catch(done); }); + + if (SUPPORTS_ASYNC) { + const testMod7 = { + handler: async (event, context) => { + if (event.test === 'success') { + return 'Success'; + } + if (event.test === 'fail') { + throw new Error('Fail'); + } + } + }; + + it('wrap + run async module 7 - await', async () => { + const w = wrapper.wrap(testMod7); + + const response = await w.run({test: 'success'}); + expect(response).to.be.equal('Success'); + }); + + it('wrap + run async module 7 - promise', (done) => { + const w = wrapper.wrap(testMod7); + + w.run({test: 'success'}) + .then((response) => { + expect(response).to.be.equal('Success'); + done(); + }) + .catch(done); + }); + + it('wrap + run async module 7 - exception', async () => { + const w = wrapper.wrap(testMod7); + + try { + const response = await w.run({test: 'fail'}); + expect(response).to.be.null; + } catch(err) { + expect(err).to.be.instanceof(Error); + } + }); + } }); if (process.env.RUN_LIVE) { From c7ed84f60d65dbd5e7c1574f3e8219b28e49ad21 Mon Sep 17 00:00:00 2001 From: Doug McCall Date: Sun, 6 May 2018 22:37:22 -0400 Subject: [PATCH 12/15] Async tests only run if Node >= v8 --- .travis.yml | 1 + test/async/async-wrapper.js | 44 +++++++++++++++++++++++++++++++++++++ test/test-wrapper.js | 40 +-------------------------------- 3 files changed, 46 insertions(+), 39 deletions(-) create mode 100644 test/async/async-wrapper.js diff --git a/.travis.yml b/.travis.yml index 6f69b86..7d4b89f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,5 +2,6 @@ language: node_js node_js: - '4.3.2' - '6.10.0' +- '8.11.1' script: - npm run unit-tests diff --git a/test/async/async-wrapper.js b/test/async/async-wrapper.js new file mode 100644 index 0000000..ee52614 --- /dev/null +++ b/test/async/async-wrapper.js @@ -0,0 +1,44 @@ +"use strict"; + +const wrapper = require("../../index.js"); +const expect = require("chai").expect; + +const testMod7 = { + handler: async (event, context) => { + if (event.test === "success") { + return "Success"; + } + if (event.test === "fail") { + throw new Error("Fail"); + } + } +}; + +describe("lambda wrapper local async", () => { + it("wrap + run async module 7 - await", async () => { + const w = wrapper.wrap(testMod7); + + const response = await w.run({ test: "success" }); + expect(response).to.be.equal("Success"); + }); + + it("wrap + run async module 7 - promise", done => { + const w = wrapper.wrap(testMod7); + + w.run({ test: "success" }).then(response => { + expect(response).to.be.equal("Success"); + done(); + }).catch(done); + }); + + it("wrap + run async module 7 - exception", async () => { + const w = wrapper.wrap(testMod7); + + try { + const response = await w.run({ test: "fail" }); + expect(response).to.be.null; + } catch (err) { + expect(err).to.be.instanceof(Error); + } + }); +}); diff --git a/test/test-wrapper.js b/test/test-wrapper.js index feb4886..b6afde7 100644 --- a/test/test-wrapper.js +++ b/test/test-wrapper.js @@ -227,45 +227,7 @@ describe('lambda-wrapper local', () => { }); if (SUPPORTS_ASYNC) { - const testMod7 = { - handler: async (event, context) => { - if (event.test === 'success') { - return 'Success'; - } - if (event.test === 'fail') { - throw new Error('Fail'); - } - } - }; - - it('wrap + run async module 7 - await', async () => { - const w = wrapper.wrap(testMod7); - - const response = await w.run({test: 'success'}); - expect(response).to.be.equal('Success'); - }); - - it('wrap + run async module 7 - promise', (done) => { - const w = wrapper.wrap(testMod7); - - w.run({test: 'success'}) - .then((response) => { - expect(response).to.be.equal('Success'); - done(); - }) - .catch(done); - }); - - it('wrap + run async module 7 - exception', async () => { - const w = wrapper.wrap(testMod7); - - try { - const response = await w.run({test: 'fail'}); - expect(response).to.be.null; - } catch(err) { - expect(err).to.be.instanceof(Error); - } - }); + require('./async/async-wrapper'); } }); From 45d765be195d77b8e9012baf63dbb0c3d12d337f Mon Sep 17 00:00:00 2001 From: mpuittinen Date: Mon, 7 May 2018 13:36:23 +0300 Subject: [PATCH 13/15] Bump version to 0.3 --- README.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b777d28..1eced9c 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ to your AWS account as 'lambdaWrapper-test'. ## Release History +* 2018/05/07 - v0.3.0 - Support for async calls, improved input validation * 2017/07/09 - v0.2.0 - Return exceptions as errors via callback * 2017/06/16 - v0.1.3 - Allow context object in run * 2016/10/21 - v0.1.2 - Support for using promises diff --git a/package.json b/package.json index 392d8b1..588957a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lambda-wrapper", - "version": "0.2.2", + "version": "0.3.0", "description": "Wrapper for running Amazon Lambda modules locally", "main": "index.js", "scripts": { From 2351b2a6159207c785682df92016316ccf21cf20 Mon Sep 17 00:00:00 2001 From: mpuittinen Date: Tue, 8 May 2018 09:03:23 +0300 Subject: [PATCH 14/15] Drop support for Node 4 (deprecated by AWS) --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7d4b89f..b03ae6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: node_js node_js: -- '4.3.2' - '6.10.0' - '8.11.1' script: From 7b1c704fa4144a94f05c84a4d5a632fffbc98112 Mon Sep 17 00:00:00 2001 From: mpuittinen Date: Tue, 8 May 2018 09:03:36 +0300 Subject: [PATCH 15/15] Add tests for async + callback --- test/async/async-wrapper.js | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/async/async-wrapper.js b/test/async/async-wrapper.js index ee52614..2907e3a 100644 --- a/test/async/async-wrapper.js +++ b/test/async/async-wrapper.js @@ -14,6 +14,17 @@ const testMod7 = { } }; +const testMod8 = { + handler: async (event, context, callback) => { + if (event.test === "success") { + callback(null, "Success"); + } + if (event.test === "fail") { + callback(new Error("Fail")); + } + } +}; + describe("lambda wrapper local async", () => { it("wrap + run async module 7 - await", async () => { const w = wrapper.wrap(testMod7); @@ -41,4 +52,31 @@ describe("lambda wrapper local async", () => { expect(err).to.be.instanceof(Error); } }); + + it("wrap + run async module 8 (callback) - await", async () => { + const w = wrapper.wrap(testMod8); + + const response = await w.run({ test: "success" }); + expect(response).to.be.equal("Success"); + }); + + it("wrap + run async module 8 (callback) - promise", done => { + const w = wrapper.wrap(testMod8); + + w.run({ test: "success" }).then(response => { + expect(response).to.be.equal("Success"); + done(); + }).catch(done); + }); + + it("wrap + run async module 8 (callback) - exception", async () => { + const w = wrapper.wrap(testMod8); + + try { + const response = await w.run({ test: "fail" }); + expect(response).to.be.null; + } catch (err) { + expect(err).to.be.instanceof(Error); + } + }); });