lambdaws
Version:
AWS lambda functions made easy
122 lines (98 loc) • 4.14 kB
JavaScript
var fs = require('fs'),
zip = require('node-zip'),
path = require('path');
require('./extensions/string');
var DEPENDENCIES_DEFAULT_FOLDER = 'node_modules',
MAX_LAMBDA_ZIP_SIZE = 25e+6;
var _generateZip = function(_zip){
var options = {
type: 'nodebuffer',
compression: 'DEFLATE'
}
var zipped = _zip.generate(options);
if(zipped.length >= MAX_LAMBDA_ZIP_SIZE) {
throw Error('The zipped function is larger than the maximum file zipe you can upload to AWS Lambda');
}
return zipped;
}
var _getDependencyFolder = function(dep) {
var depFolder = path.dirname(require.resolve(dep)) + path.sep;
var subFolders = depFolder.split(path.sep);
var node_modules_index = subFolders.lastIndexOf('node_modules') + 1; // Zero-based indexes
var folders = subFolders.splice(0, node_modules_index + 1); // We select the next folder
return folders.join(path.sep); // TODO throw better errors if require fails
};
var _addDepsToZip = function(_zip, deps){
var depsFolders = deps
.filter(function(dep){
return !dep.startsWith(global.constants.EXTERNALS_PREPENDING_STR)
&& !dep.startsWith(global.constants.INTERNALS_PREPENDING_STR);
})
.map(function(dep) {
return _getDependencyFolder(dep);
}).filter(function(dep){
// we exclude those deps because they are built-in node and zipping . folder is not wanted
return dep !== '.';
});
var zipModules = _zip.folder(DEPENDENCIES_DEFAULT_FOLDER);
depsFolders.forEach(function(folder) {
_addFolderRecursiveToZipNode(folder, zipModules);
});
}
var _addFolderRecursiveToZipNode = function(folder, zipNode) {
var basename = path.basename(folder);
var node = zipNode.folder(basename);
var files = fs.readdirSync(folder);
files.forEach(function(file) {
var fullPath = path.join(folder, file);
if(fs.statSync(fullPath).isDirectory())
_addFolderRecursiveToZipNode(fullPath, node);
else // TODO It would be nice to exclude non-mandatory files like .md, .txt etc
node.file(file, fs.readFileSync(fullPath));
});
};
var _addHandlersToZip = function(zip, configs) {
var callbackHandler = !!configs.ignoreResponse ? '_emptyCallbackHandler.js' : '_SQSCallbackHandler.js';
var callbackHandlerFile = fs.readFileSync(__dirname + '/internals/' + callbackHandler);
var externalsHandlerFile = fs.readFileSync(__dirname + '/internals/_externalsHandler.js');
var utilsFile = fs.readFileSync(__dirname + '/internals/_utils.js');
zip.file('_callbackHandler.js', callbackHandlerFile);
zip.file('_externalsHandler.js', externalsHandlerFile);
zip.file('_utils.js', utilsFile);
};
var _addInternalsToZip = function(zip, deps) {
var internals = deps.filter(function(d) {
return d.startsWith(global.constants.INTERNALS_PREPENDING_STR);
});
if(internals.length === 0) return;
var node = zip.folder(global.constants.INTERNALS_FOLDER_NAME);
for(var i in internals) {
var internal = internals[i].substr(global.constants.INTERNALS_PREPENDING_STR.length);
var fileName = path.basename(internal);
node.file(fileName, fs.readFileSync(internal));
}
};
module.exports = {
zipFunction : function(stringFunc, deps, configs){
var _zip = zip();
_zip.file('index.js', stringFunc);
_addHandlersToZip(_zip, configs);
_addInternalsToZip(_zip, deps);
if (deps) {
_addDepsToZip(_zip, deps);
}
return _generateZip(_zip);
},
zipModule : function(moduleOverride, modulePath, deps, configs){
var _zip = zip();
var moduleFile = fs.readFileSync(modulePath);
_zip.file('module.js', moduleFile);
_zip.file('index.js', moduleOverride);
_addHandlersToZip(_zip, configs);
_addInternalsToZip(_zip, deps);
if (deps) {
_addDepsToZip(_zip, deps);
}
return _generateZip(_zip);
}
}