diff --git a/bin/jaws b/bin/jaws index f6bd8dad2..e7c464a88 100755 --- a/bin/jaws +++ b/bin/jaws @@ -17,7 +17,7 @@ program 'stack which provisions essential AWS resources for your JAWS project.') .option('-n, --proj-name ', 'Project name') .option('-s, --stage ', 'Stage to create') - .option('-r, --lambda-region ', 'Region lambda(s) will be created in') + .option('-r, --lambda-region ', 'Region lambda(s) will be created in. Only support 1 currently') .option('-e, --notification-email ', 'Email to be notified with stack alerts') .option('-p, --profile ', 'AWS profile to use (as defined in ~/.aws/credentials)') .action(function(options) { @@ -63,8 +63,7 @@ program }); //TODO: add untag feature -//TODO: add tag all feature -//TODO: add untag all feature +//TODO: add tag/untag all feature program .command('tag') .description('Tag a lambda function to be deployed the next time you run the deploy command for all' + diff --git a/lib/commands/deploy_lambda.js b/lib/commands/deploy_lambda.js index c9081e3a6..accc9cd06 100644 --- a/lib/commands/deploy_lambda.js +++ b/lib/commands/deploy_lambda.js @@ -13,6 +13,9 @@ var JawsError = require('../jaws-error'), async = require('async'), AWSUtils = require('../utils/aws'), utils = require('../utils/index'), + browserify = require('browserify'), + UglifyJS = require('uglify-js'), + zip = new require('node-zip')(), extend = require('util')._extend; //OK per Isaacs and http://stackoverflow.com/a/22286375/563420 Promise.promisifyAll(fs); @@ -33,9 +36,19 @@ module.exports = function(JAWS) { }); }; - JAWS._packageNodeJs = function(distDir, fullLambdaName, jawsFilePath, excludeFiles) { - var jawsJson = require(jawsFilePath), - baseDir = path.dirname(jawsFilePath), + /** + * Package up nodejs lambda + * + * @param tmpDistDir + * @param fullLambdaName + * @param jawsFilePath + * @param excludeFiles + * @param ignoreFiles + * @returns {Promise} {jawsFilePath: jawsFilePath,zipBuffer:zippedData} + * @private + */ + JAWS._packageNodeJs = function(tmpDistDir, fullLambdaName, jawsFilePath, excludeFiles, ignoreFiles) { + var baseDir = path.dirname(jawsFilePath), b = browserify({ entries: path.join(baseDir, 'index.js'), node: true, @@ -47,34 +60,78 @@ module.exports = function(JAWS) { b.exclude(file); }); + ignoreFiles.forEach(function(file) { + b.ignore(file); + }); + var uglyOptions = { mangle: true, - compress: {}, + compress: {}, //@see http://lisperator.net/uglifyjs/compress }; - //TODO: save the browserfied js to the fs (browserfied.js) so we have audit trail - //b.bundle() - // .pipe() + return new Promise(function(resolve, reject) { + //Save the browserfied js to so we have audit trail + var broserfiedFile = path.join(tmpDistDir, 'browserfied.js'), + uglifiedFile = path.join(tmpDistDir, 'index.js'), + bFile = fs.createWriteStream(broserfiedFile); + b.bundle().pipe(bFile); - //uglify and save as index.js + bFile + .on('finish', function() { + //uglify and save as index.js + var result = UglifyJS.minify(broserfiedFile, uglyOptions); //minify does not expose its internal stream :( - //compress and save as zip + if (!result || !result.code) { + reject(new JawsError('Problem uglifying code'), JawsError.errorCodes.UNKNOWN); + } + + fs.writeFileSync(uglifiedFile, result.code); + + //compress and save as zip node buffer + zip.file('index.js', result.code); + + var zippedData = zip.generate({ + type: 'nodebuffer', + compression: 'DEFLATE', + }); + + if (zippedData.length > 52428800) { + reject(new JawsError( + 'Zip file is > the 50MB Lambda deploy limit (' + zippedData.length + ' bytes)', + JawsError.errorCodes.ZIP_TOO_BIG) + ); + } + + resolve({jawsFilePath: jawsFilePath, zipBuffer: zippedData}); + }) + .on('error', function(err) { + reject(err); + }); + }); }; + /** + * Create lambda package for deployment + * + * @param jawsFilePath + * @param stage + * @returns {Promise} {jawsFilePath: jawsFilePath,zipBuffer:zippedData} + * @private + */ JAWS._bundleLambda = function(jawsFilePath, stage) { var _this = this, jawsJson = require(jawsFilePath), projName = JAWS._meta.projectJson.name, fullLambdaName = [stage, projName, jawsJson.lambda.name].join('_-_'), - distDir = path.join(os.tmpdir(), fullLambdaName + '@' + new Date()); + tmpDistDir = path.join(os.tmpdir(), fullLambdaName + '@' + new Date()); - console.log('Bundling', fullLambdaName, 'in tmp dir', distDir); + console.log('Creating dist for', fullLambdaName, 'in tmp dir', tmpDistDir); - fs.mkdirSync(distDir); + fs.mkdirSync(tmpDistDir); switch (jawsJson.lambda.runtime) { case 'nodejs': - return _this._packageNodeJs(distDir); + return _this._packageNodeJs(tmpDistDir); break; default: return Promise.reject(new JawsError( @@ -84,6 +141,10 @@ module.exports = function(JAWS) { } }; + JAWS._createOrUpdateLambda = function(jawsFilePath, zipBuffer) { + + }; + /** * Deploy lambda at cwd or if deployAll is true does all tag lambdas under back dir * @@ -113,7 +174,7 @@ module.exports = function(JAWS) { return Promise.all(builderQueue); }) - .then(function(builtLambdas) { + .then(function(packagedLambdas) { }); }; diff --git a/lib/commands/new.js b/lib/commands/new.js index 13dd44255..46c5fae3a 100644 --- a/lib/commands/new.js +++ b/lib/commands/new.js @@ -86,7 +86,7 @@ function _getAnswers(projName, stage, lambdaRegion, notificationEmail, awsProfil prompts.push({ type: 'rawlist', name: 'region', - message: 'Which AWS Region would you like to use (you can change these later)?', + message: 'Which AWS Region would you like to use (can change later. only support one at this time)?', default: 'us-east-1', choices: [ 'us-east-1', diff --git a/lib/jaws-error/index.js b/lib/jaws-error/index.js index c59e6f00c..f1e778238 100644 --- a/lib/jaws-error/index.js +++ b/lib/jaws-error/index.js @@ -27,4 +27,5 @@ module.exports.errorCodes = { MISSING_AWS_CREDS_PROFILE: 3, MISSING_AWS_CREDS: 4, INVALID_PROJ_NAME: 5, + ZIP_TOO_BIG: 6, }; diff --git a/package.json b/package.json index c99cdf7a5..2ce53754c 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,6 @@ "node-uuid": "^1.4.2", "node-zip": "^1.1.0", "nodemon": "^1.3.8", - "prettysize": "0.0.3", "readdirp": "^1.4.0", "replace": "^0.3.0", "rimraf": "^2.2.8",