serverless/lib/RuntimeNode.js
2016-03-14 14:25:27 -07:00

180 lines
4.8 KiB
JavaScript

'use strict';
const SError = require('./Error'),
RuntimeBase = require('./RuntimeBase'),
SCli = require('./utils/cli'),
_ = require('lodash'),
BbPromise = require('bluebird'),
chalk = require('chalk'),
context = require('./utils/context'),
path = require('path'),
fs = BbPromise.promisifyAll(require('fs'));
let SUtils;
class ServerlessRuntimeNode extends RuntimeBase {
constructor(S) {
super( S, 'nodejs' );
SUtils = S.utils;
}
/**
* Scaffold
* - Create scaffolding for new Node.js function
*/
scaffold(func) {
const handlerPath = path.join(this.S.getServerlessPath(), 'templates', 'nodejs', 'handler.js');
return fs.readFileAsync(handlerPath)
.then(handlerJs => BbPromise.all([
SUtils.writeFile(func.getRootPath('handler.js'), handlerJs),
SUtils.writeFile(func.getRootPath('event.json'), {})
]));
}
/**
* Run
* - Run this function locally
*/
run(func) {
let _this = this,
functionEvent,
functionCall;
return BbPromise.try(function() {
// Load Event
functionEvent = SUtils.readFileSync(func.getRootPath('event.json'));
// Load Function
let handlerArr = func.handler.split('/').pop().split('.'),
functionFile = func.getRootPath(handlerArr[0] + '.js'),
functionHandler = handlerArr[1];
functionCall = require(functionFile)[functionHandler];
})
.then(() => _this.getEnvVars(func))
.then(function(envVars) {
// Add ENV vars (from no stage/region) to environment
for (var key in envVars) {
process.env[key] = envVars[key];
}
})
.then(() => {
return new BbPromise(resolve => {
// Call Function
functionCall(functionEvent, context(func, (err, result) => {
SCli.log(`-----------------`);
// Show error
if (err) {
SCli.log(chalk.bold('Failed - This Error Was Returned:'));
SCli.log(err.message);
SCli.log(err.stack);
return resolve({
status: 'error',
response: err.message,
error: err
});
}
// Show success response
SCli.log(chalk.bold('Success! - This Response Was Returned:'));
SCli.log(JSON.stringify(result, null, 4));
return resolve({
status: 'success',
response: result
});
}));
})
})
.catch((err) => {
SCli.log(`-----------------`);
SCli.log(chalk.bold('Failed - This Error Was Thrown:'));
SCli.log(err.stack || err);
return {
status: 'error',
response: err.message,
error: err
};
});
}
/**
* Build
* - Build the function in this runtime
*/
build(func, stage, region) {
// Validate
if (!func._class || func._class !== 'Function') return BbPromise.reject(new SError('A function instance is required'));
let pathDist;
return this.createDistDir(func.name)
.then(function(distDir) { pathDist = distDir })
.then(() => this.copyFunction(func, pathDist, stage, region))
.then(() => this._addEnvVarsInline(func, pathDist, stage, region))
.then(() => this.generatePaths(func, pathDist));
}
/**
* Get Handler
*/
getHandler(func) {
return path.join(path.dirname(func.handler), "_serverless_handler.handler").replace(/\\/g, '/');
}
/**
* Install NPM Dependencies
*/
installDependencies(dir) {
SCli.log(`Installing NPM dependencies in dir: ${dir}`);
SCli.log(`-----------------`);
SUtils.npmInstall(this.S.getProject().getRootPath(dir));
SCli.log(`-----------------`);
}
/**
* Add ENV Vars In-line
* - Adds a new handler that loads in ENV vars before running the main handler
*/
_addEnvVarsInline(func, pathDist, stage, region) {
return this.getEnvVars(func, stage, region)
.then(envVars => {
const handlerArr = func.handler.split('.'),
handlerDir = path.dirname(func.handler),
handlerFile = handlerArr[0].split('/').pop(),
handlerMethod = handlerArr[1];
const loader = `
var envVars = ${JSON.stringify(envVars, null, 2)};
for (var key in envVars) {
process.env[key] = envVars[key];
}
exports.handler = require("./${handlerFile}")["${handlerMethod}"];
`;
return fs.writeFileAsync(path.join(pathDist, handlerDir, '_serverless_handler.js'), loader);
});
}
}
module.exports = ServerlessRuntimeNode;