Support returning promises from serverless.js

This commit is contained in:
Simon Buchan 2018-03-14 18:53:52 +13:00
parent bd196e0508
commit 33759c2736
4 changed files with 77 additions and 4 deletions

View File

@ -69,8 +69,10 @@ class Service {
return BbPromise.try(() => {
// use require to load serverless.js file
// eslint-disable-next-line global-require
const config = require(serviceFilePath);
const configExport = require(serviceFilePath);
// In case of a promise result, first resolve it.
return configExport;
}).then(config => {
if (!_.isPlainObject(config)) {
throw new Error('serverless.js must export plain object');
}

View File

@ -342,6 +342,61 @@ describe('Service', () => {
});
});
it('should load serverless.js from filesystem', () => {
const SUtils = new Utils();
const serverlessJSON = {
service: 'new-service',
provider: {
name: 'aws',
stage: 'dev',
region: 'us-east-1',
variableSyntax: '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}',
},
plugins: ['testPlugin'],
functions: {
functionA: {},
},
resources: {
aws: {
resourcesProp: 'value',
},
azure: {},
google: {},
},
package: {
exclude: ['exclude-me'],
include: ['include-me'],
artifact: 'some/path/foo.zip',
},
};
SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.js'),
`module.exports = new Promise(resolve => { resolve(${JSON.stringify(serverlessJSON)}) });`);
const serverless = new Serverless();
serverless.config.update({ servicePath: tmpDirPath });
serviceInstance = new Service(serverless);
return expect(serviceInstance.load()).to.eventually.be.fulfilled
.then(() => {
expect(serviceInstance.service).to.be.equal('new-service');
expect(serviceInstance.provider.name).to.deep.equal('aws');
expect(serviceInstance.provider.variableSyntax).to.equal(
'\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}'
);
expect(serviceInstance.plugins).to.deep.equal(['testPlugin']);
expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' });
expect(serviceInstance.resources.azure).to.deep.equal({});
expect(serviceInstance.resources.google).to.deep.equal({});
expect(serviceInstance.package.exclude.length).to.equal(1);
expect(serviceInstance.package.exclude[0]).to.equal('exclude-me');
expect(serviceInstance.package.include.length).to.equal(1);
expect(serviceInstance.package.include[0]).to.equal('include-me');
expect(serviceInstance.package.artifact).to.equal('some/path/foo.zip');
expect(serviceInstance.package.excludeDevDependencies).to.equal(undefined);
});
});
it('should throw error if serverless.js exports invalid config', () => {
const SUtils = new Utils();

View File

@ -28,8 +28,10 @@ const getServerlessConfigFile = _.memoize((servicePath) => {
return BbPromise.try(() => {
// use require to load serverless.js
// eslint-disable-next-line global-require
const config = require(jsPath);
const configExport = require(jsPath);
// In case of a promise result, first resolve it.
return configExport;
}).then(config => {
if (_.isPlainObject(config)) {
return config;
}

View File

@ -63,6 +63,20 @@ describe('#getServerlessConfigFile()', () => {
);
});
it('should return the resolved value if a promise-using serverless.js file found', () => {
const serverlessFilePath = path.join(tmpDirPath, 'serverless.js');
writeFileSync(
serverlessFilePath,
'module.exports = new Promise(resolve => { resolve({"service": "my-json-service"}); });'
);
return expect(getServerlessConfigFile(tmpDirPath)).to.be.fulfilled.then(
(result) => {
expect(result).to.deep.equal({ service: 'my-json-service' });
}
);
});
it('should throw an error, if serverless.js export not a plain object', () => {
const serverlessFilePath = path.join(tmpDirPath, 'serverless.js');
writeFileSync(