serverless/lib/RuntimeBase.js
2016-03-14 21:46:44 +07:00

178 lines
4.6 KiB
JavaScript

'use strict';
const SError = require('./Error'),
BbPromise = require('bluebird'),
fs = BbPromise.promisifyAll(require('fs')),
path = require('path'),
wrench = require('wrench'),
_ = require('lodash');
/**
* This is the base class that all Serverless Runtimes should extend.
*/
let SUtils;
class ServerlessRuntimeBase {
constructor(S, name) {
SUtils = S.utils;
this.S = S;
this.name = name;
}
installDepedencies( dir ) {
return BbPromise.reject(new SError(`Runtime "${this.getName()}" should implement "installDepedencies()" method`));
}
// Helper methods for derived classes
getName() {
return this.name;
}
scaffold(func) {
return BbPromise.resolve();
}
run(func) {
return BbPromise.reject(new SError(`Runtime "${this.getName()}" should implement "run()" method`));
}
build(func, pathDist, stage, region) {
return this._copyDir(func, pathDist, stage, region)
.then(() => this._afterCopyDir(func, pathDist, stage, region))
.then(() => this._generateIncludePaths(func, pathDist));
}
_copyDir(func, pathDist, stage, region) {
return BbPromise.try(() => {
// Status
SUtils.sDebug(`"${stage} - ${region} - ${func.getName()}": Copying in dist dir ${pathDist}`);
// Extract the root of the lambda package from the handler property
let handlerFullPath = func.getRootPath(func.handler.split('/')[func.handler.split('/').length - 1]).replace(/\\/g, '/');
// Check handler is correct
if (handlerFullPath.indexOf(func.handler) == -1) {
throw new SError('This function\'s handler is invalid and not in the file system: ' + func.handler);
}
let packageRoot = handlerFullPath.replace(func.handler, '');
return wrench.copyDirSyncRecursive(packageRoot, pathDist, {
exclude: this._exclude(func, pathDist, stage, region)
});
});
}
_exclude(func, pathDist, stage, region) {
// Copy entire test project to temp folder, don't include anything in excludePatterns
let excludePatterns = func.custom.excludePatterns || [];
return function(name, prefix) {
if (!excludePatterns.length) { return false;}
let relPath = path.join(prefix.replace(pathDist, ''), name);
return excludePatterns.some(sRegex => {
relPath = (relPath.charAt(0) == path.sep) ? relPath.substr(1) : relPath;
let re = new RegExp(sRegex),
matches = re.exec(relPath),
willExclude = (matches && matches.length > 0);
if (willExclude) {
SUtils.sDebug(`"${stage} - ${region} - ${func.name}": Excluding - ${relPath}`);
}
return willExclude;
});
}
}
_getEnvVars(func, stage, region) {
const envVars = func.toObjectPopulated({stage, region}).environment,
project = this.S.getProject();
const defaultVars = {
SERVERLESS_STAGE: stage,
SERVERLESS_DATA_MODEL_STAGE: project.getStage(stage).getName(),
SERVERLESS_PROJECT_NAME: project.getName()
};
return BbPromise.resolve(_.defaults(envVars, defaultVars));
}
_afterCopyDir(func, pathDist, stage, region) {
return BbPromise.resolve();
}
_generateIncludePaths(func, pathDist) {
let compressPaths = [],
ignore = ['.DS_Store'],
stats,
fullPath;
// Zip up whatever is in back
let includePaths = func.custom.includePaths || ['.'];
includePaths.forEach(p => {
try {
fullPath = path.resolve(path.join(pathDist, p));
stats = fs.lstatSync(fullPath);
} catch (e) {
console.error('Cant find includePath ', p, e);
throw e;
}
if (stats.isFile()) {
compressPaths.push({
name: p,
path: fullPath
});
} else if (stats.isDirectory()) {
let dirname = path.basename(p);
wrench
.readdirSyncRecursive(fullPath)
.forEach(file => {
// Ignore certain files
for (let i = 0; i < ignore.length; i++) {
if (file.toLowerCase().indexOf(ignore[i]) > -1) return;
}
let filePath = path.join(fullPath, file);
if (fs.lstatSync(filePath).isFile()) {
let pathInZip = path.join(dirname, file);
compressPaths.push({
name: pathInZip,
path: filePath
});
}
});
}
});
return BbPromise.resolve(compressPaths);
}
getHandler(func) {
return func.handler;
}
}
module.exports = ServerlessRuntimeBase;