serverless/lib/utils/index.js
2015-09-06 22:05:41 -05:00

275 lines
6.7 KiB
JavaScript

'use strict';
/**
* JAWS CLI: Utilities
*/
var Promise = require('bluebird'),
path = require('path'),
async = require('async'),
readdirp = require('readdirp'),
JawsError = require('../jaws-error'),
fs = require('fs'),
mkdirpAsync = require('mkdirp-then');
Promise.promisifyAll(fs);
/**
* Find all jaws paths of given type
*
* @param projectRootPath
* @param type lambda|api
*/
module.exports.findAllJawsPathsOfType = function(projectRootPath, type) {
var _this = this,
jawsJsonAttr;
switch (type) {
case 'lambda':
jawsJsonAttr = 'lambda';
break;
case 'api':
jawsJsonAttr = 'endpoint';
break;
default:
return Promise.reject(new JawsError('Invalid type ' + type, JawsError.errorCodes.UNKNOWN));
break;
}
return _this.readRecursively(path.join(projectRootPath, 'back'), '*jaws.json')
.then(function(jsonPaths) {
return new Promise(function(resolve, reject) {
var jawsPathsOfType = [];
// Check each file to ensure it is a lambda
async.eachLimit(jsonPaths, 10, function(jsonPath, cb) {
var lambdaJawsPath = path.join(projectRootPath, 'back', jsonPath),
json = require(lambdaJawsPath);
if (typeof json[jawsJsonAttr] !== 'undefined') jawsPathsOfType.push(lambdaJawsPath);
return cb();
},
function(error) {
if (error) reject(error);
resolve(jawsPathsOfType);
});
});
});
};
/**
* Find project root path
*
* @param startDir
* @returns {*}
*/
module.exports.findProjectRootPath = function(startDir) {
// Check if startDir is root
if (fs.existsSync(path.join(startDir, 'jaws.json'))) {
var jawsJsonInDir = require(path.join(startDir, 'jaws.json'));
if (typeof jawsJsonInDir.project !== 'undefined') return path.resolve(startDir);
}
// Check up to 10 parent levels
var previous = './',
projRootPath = false;
for (var i = 0; i < 10; i++) {
previous = path.join(previous, '../');
var fullPath = path.resolve(startDir, previous);
if (fs.existsSync(path.join(fullPath, 'jaws.json'))) {
var jawsJson = require(path.join(fullPath, 'jaws.json'));
if (typeof jawsJson.project !== 'undefined') {
projRootPath = fullPath;
break;
}
}
}
return projRootPath;
};
/**
* Handle exit
*
* @param promise
*/
module.exports.handleExit = function(promise) {
promise
.catch(JawsError, function(e) {
console.error(e);
process.exit(e.messageId);
})
.error(function(e) {
console.error(e);
process.exit(1);
})
.done();
};
/**
* Read Recursively
* @param path
* @param filter
* @returns {Promise}
*/
module.exports.readRecursively = function(path, filter) {
return new Promise(function(resolve, reject) {
var files = [];
readdirp({
root: path,
fileFilter: filter,
})
.on('data', function(entry) {
files.push(entry.path);
})
.on('error', function(error) {
reject(error);
})
.on('end', function() {
resolve(files);
});
});
};
/**
* Find all dirs that are lambdas
*
* @param projectRootPath
* @returns {Promise} list of full paths to jaws.json files that are type lambda
*/
module.exports.findAllLambdas = function(projectRootPath) {
return this.findAllJawsPathsOfType(projectRootPath, 'lambda');
};
/**
* Find all dirs that are endpoints
*
* @param projectRootPath
* @returns {Promise} list of full paths to jaws.json files that are type api
*/
module.exports.findAllEndpoints = function(projectRootPath) {
return this.findAllJawsPathsOfType(projectRootPath, 'api');
};
/**
* Find all jaws json paths underneath given dir
*
* @param startPath
* @returns {Promise} list of full paths to jaws.json files
*/
module.exports.findAllJawsJsons = function(startPath) {
return this.readRecursively(startPath, '*jaws.json')
.then(function(jsonPaths) {
return jsonPaths.map(function(jsonPath) {
return path.resolve(path.join(startPath, jsonPath));
});
});
};
/**
* Write to console.log if process.env.JAWS_VERBOSE is true
*
* If we ever want to get more complicated with log levels we should use winston
*
* @param str
*/
module.exports.logIfVerbose = function(str) {
if (process.env.JAWS_VERBOSE) {
console.log(str);
}
};
/**
* Writes file and makes any parent dirs if necessary
*
* @param filePath
* @param contents node Buffer
* @returns {Promise}
*/
module.exports.writeFile = function(filePath, contents) {
return mkdirpAsync(path.dirname(filePath))
.then(function() {
return fs.writeFileAsync(filePath, contents);
});
};
/**
* Checks for duplicate lambda functionName's
*
* @param projectRootPath
* @returns {Promise} list of lambdaJawsPaths
*/
module.exports.checkForDuplicateLambdaNames = function(projectRootPath) {
var lambdaNameMap = {};
return this.findAllLambdas(projectRootPath)
.then(function(lambdaJawsPaths) {
//Verify 2 lambdas dont have same name
lambdaJawsPaths.forEach(function(ljp) {
var ljpJson = require(ljp);
if (lambdaNameMap[ljpJson.lambda.functionName]) {
throw new JawsError(
'Lambda named ' + ljpJson.lambda.functionName + ' exists twice in your project',
JawsError.errorCodes.UNKNOWN
);
} else {
lambdaNameMap[ljpJson.lambda.functionName] = true;
}
});
return lambdaJawsPaths;
});
};
/**
* Gets all lambda functionName's
*
* @param projectRootPath
* @returns {Promise} list of functionName's
*/
module.exports.getAllLambdaNames = function(projectRootPath) {
var lambdaNames = [];
return this.findAllLambdas(projectRootPath)
.then(function(lambdaJawsPaths) {
lambdaJawsPaths.forEach(function(ljp) {
var ljpJson = require(ljp);
lambdaNames.push(ljpJson.lambda.functionName);
});
return lambdaNames;
});
};
/**
* Given list of project stages objects, extract given region
*
* @param projectStageObj
* @param region
* @returns {*} region object for stage
*/
module.exports.getProjRegionConfig = function(projectStageObj, region) {
var region = projectStageObj.filter(function(regionObj) {
return regionObj.region == region;
});
if (!region || region.length == 0) {
throw new JawsError('Could not find region ' + region, JawsError.errorCodes.UNKNOWN);
}
if (region.length > 1) {
throw new JawsError('Multiple regions named ' + region, JawsError.errorCodes.UNKNOWN);
}
return region[0];
};